summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-10-27 22:54:32 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-10-27 22:54:32 -0300
commite82dc402052a47b44bb3bcf50ee4801257f92778 (patch)
tree01c2cd8692b5569cae778f6504b76b3d1f9ccdad /servers
parent9608d4255eb6c76b1c4496f4494c829133e096f4 (diff)
-Much improvement to baked light baker
-Fixed many bugs in stretch mode -Fixes to camera project and unproject as consequence of the above -added setget to script (documented in script doc) -more fixes to collada exporter for blender
Diffstat (limited to 'servers')
-rw-r--r--servers/visual/rasterizer.h7
-rw-r--r--servers/visual/rasterizer_dummy.cpp20
-rw-r--r--servers/visual/rasterizer_dummy.h11
-rw-r--r--servers/visual/visual_server_raster.cpp639
-rw-r--r--servers/visual/visual_server_raster.h66
-rw-r--r--servers/visual/visual_server_wrap_mt.h17
-rw-r--r--servers/visual_server.h30
7 files changed, 782 insertions, 8 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index dc970383b6..55625a2218 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -503,6 +503,7 @@ public:
VS::BakedLightMode mode;
RID octree_texture;
+ RID light_texture;
float color_multiplier; //used for both lightmaps and octree
Transform octree_transform;
Map<int,RID> lightmaps;
@@ -514,6 +515,7 @@ public:
float lightmap_multiplier;
int octree_steps;
Vector2 octree_tex_pixel_size;
+ Vector2 light_tex_pixel_size;
};
struct InstanceData {
@@ -521,6 +523,7 @@ public:
Transform transform;
RID skeleton;
RID material_override;
+ RID sampled_light;
Vector<RID> light_instances;
Vector<float> morph_values;
BakedLightData *baked_light;
@@ -586,6 +589,10 @@ public:
virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0;
virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0;
+ /* SAMPLED LIGHT */
+ virtual RID sampled_light_dp_create(int p_width,int p_height)=0;
+ virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0;
+
/*MISC*/
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
index 637c251cf1..a671821e25 100644
--- a/servers/visual/rasterizer_dummy.cpp
+++ b/servers/visual/rasterizer_dummy.cpp
@@ -1679,6 +1679,18 @@ Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar
}
+
+RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) {
+
+ return sampled_light_owner.make_rid(memnew(SampledLight));
+}
+
+void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) {
+
+
+}
+
+
/*MISC*/
bool RasterizerDummy::is_texture(const RID& p_rid) const {
@@ -1816,6 +1828,14 @@ void RasterizerDummy::free(const RID& p_rid) {
Environment *env = environment_owner.get( p_rid );
environment_owner.free(p_rid);
memdelete( env );
+ } else if (sampled_light_owner.owns(p_rid)) {
+
+ SampledLight *sampled_light = sampled_light_owner.get( p_rid );
+ ERR_FAIL_COND(!sampled_light);
+
+ sampled_light_owner.free(p_rid);
+ memdelete( sampled_light );
+
};
}
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
index 373564249e..44bca423a4 100644
--- a/servers/visual/rasterizer_dummy.h
+++ b/servers/visual/rasterizer_dummy.h
@@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer {
mutable RID_Owner<Environment> environment_owner;
+ struct SampledLight {
+
+ int w,h;
+ };
+
+ mutable RID_Owner<SampledLight> sampled_light_owner;
+
struct ShadowBuffer;
struct LightInstance {
@@ -713,6 +720,10 @@ public:
virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value);
virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const;
+ /* SAMPLED LIGHT */
+ virtual RID sampled_light_dp_create(int p_width,int p_height);
+ virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier);
+
/*MISC*/
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 8250e4c08f..13ecd49b68 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -1109,8 +1109,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
int tex_w;
int tex_h;
+ int light_tex_w;
+ int light_tex_h;
bool is16;
+ bool has_light_tex=false;
{
+
DVector<uint8_t>::Read r=p_octree.read();
tex_w = decode_uint32(&r[0]);
tex_h = decode_uint32(&r[4]);
@@ -1123,7 +1127,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
baked_light->data.octree_steps=decode_uint32(&r[16]);
baked_light->data.octree_tex_pixel_size.x=1.0/tex_w;
baked_light->data.octree_tex_pixel_size.y=1.0/tex_h;
+
baked_light->data.texture_multiplier=decode_uint32(&r[20]);
+ light_tex_w=decode_uint16(&r[24]);
+ light_tex_h=decode_uint16(&r[26]);
+ print_line("ltexw "+itos(light_tex_w));
+ print_line("ltexh "+itos(light_tex_h));
+
+ if (light_tex_w>0 && light_tex_h>0) {
+ baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w;
+ baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h;
+ has_light_tex=true;
+ } else {
+ baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size;
+
+ }
+
baked_light->octree_aabb.pos.x=decode_float(&r[32]);
@@ -1141,12 +1160,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
rasterizer->free(baked_light->data.octree_texture);
baked_light->data.octree_texture=RID();
+ baked_light->octree_tex_size.x=0;
+ baked_light->octree_tex_size.y=0;
+ }
+ }
+
+ if (baked_light->data.light_texture.is_valid()) {
+ if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) {
+ rasterizer->free(baked_light->data.light_texture);
+ baked_light->data.light_texture=RID();
+ baked_light->light_tex_size.x=0;
+ baked_light->light_tex_size.y=0;
}
}
if (!baked_light->data.octree_texture.is_valid()) {
baked_light->data.octree_texture=rasterizer->texture_create();
rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER);
+ baked_light->octree_tex_size.x=tex_w;
+ baked_light->octree_tex_size.y=tex_h;
+ }
+
+ if (!baked_light->data.light_texture.is_valid() && has_light_tex) {
+ baked_light->data.light_texture=rasterizer->texture_create();
+ rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER);
+ baked_light->light_tex_size.x=light_tex_w;
+ baked_light->light_tex_size.y=light_tex_h;
+
}
Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree);
@@ -1159,6 +1199,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
}
+
DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{
@@ -1174,6 +1215,67 @@ DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) c
}
}
+void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) {
+
+ VS_CHANGED;
+ BakedLight *baked_light = baked_light_owner.get(p_baked_light);
+ ERR_FAIL_COND(!baked_light);
+ ERR_FAIL_COND(p_light.size()==0);
+
+ int tex_w=baked_light->light_tex_size.x;
+ int tex_h=baked_light->light_tex_size.y;
+
+ ERR_FAIL_COND(tex_w==0 && tex_h==0);
+ ERR_FAIL_COND(!baked_light->data.light_texture.is_valid());
+
+
+
+ print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size()));
+
+ Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light);
+ rasterizer->texture_set_data(baked_light->data.light_texture,img);
+
+
+
+}
+
+DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{
+
+ BakedLight *baked_light = baked_light_owner.get(p_baked_light);
+ ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>());
+
+ if (rasterizer->is_texture(baked_light->data.light_texture)) {
+
+ Image img = rasterizer->texture_get_data(baked_light->data.light_texture);
+ return img.get_data();
+ } else {
+ return DVector<uint8_t>();
+ }
+}
+
+
+
+void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) {
+
+ BakedLight *baked_light = baked_light_owner.get(p_baked_light);
+ ERR_FAIL_COND(!baked_light);
+
+ baked_light->sampler=p_sampler;
+
+
+
+}
+
+DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const {
+
+ BakedLight *baked_light = baked_light_owner.get(p_baked_light);
+ ERR_FAIL_COND_V(!baked_light,DVector<int>());
+
+ return baked_light->sampler;
+
+}
+
+
void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){
VS_CHANGED;
@@ -1192,6 +1294,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){
}
+/* BAKED LIGHT SAMPLER */
+
+RID VisualServerRaster::baked_light_sampler_create() {
+
+ BakedLightSampler * blsamp = memnew( BakedLightSampler );
+ RID rid = baked_light_sampler_owner.make_rid(blsamp);
+ _update_baked_light_sampler_dp_cache(blsamp);
+ return rid;
+}
+
+void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){
+
+ VS_CHANGED;
+ BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
+ ERR_FAIL_COND(!blsamp);
+ ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX);
+ blsamp->params[p_param]=p_value;
+ _dependency_queue_update(p_baked_light_sampler,true);
+}
+
+float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{
+
+
+ BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
+ ERR_FAIL_COND_V(!blsamp,0);
+ ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0);
+ return blsamp->params[p_param];
+}
+
+void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) {
+
+ int res = blsamp->resolution;
+ blsamp->dp_cache.resize(res*res*2);
+ Vector3 *dp_normals=blsamp->dp_cache.ptr();
+
+ for(int p=0;p<2;p++) {
+ float sign = p==0?1:-1;
+ int ofs = res*res*p;
+ for(int i=0;i<res;i++) {
+ for(int j=0;j<res;j++) {
+
+ Vector2 v(
+ (i/float(res))*2.0-1.0,
+ (j/float(res))*2.0-1.0
+ );
+
+ float l=v.length();
+ if (l>1.0) {
+ v/=l;
+ l=1.0; //clamp to avoid imaginary
+ }
+ v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function
+ Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z
+ n.y*=sign;
+ dp_normals[j*res+i+ofs]=n;
+ }
+ }
+ }
+
+}
+
+void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){
+
+ ERR_FAIL_COND(p_resolution<4 && p_resolution>64);
+ VS_CHANGED;
+ BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
+ ERR_FAIL_COND(!blsamp);
+ blsamp->resolution=p_resolution;
+ _update_baked_light_sampler_dp_cache(blsamp);
+
+}
+int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{
+
+ BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
+ ERR_FAIL_COND_V(!blsamp,0);
+ return blsamp->resolution;
+}
+
/* CAMERA API */
RID VisualServerRaster::camera_create() {
@@ -1943,6 +2123,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
}
+ if (instance->baked_light_sampler_info) {
+
+ while (instance->baked_light_sampler_info->owned_instances.size()) {
+
+ instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID());
+ }
+
+ if (instance->baked_light_sampler_info->sampled_light.is_valid()) {
+ rasterizer->free(instance->baked_light_sampler_info->sampled_light);
+ }
+ memdelete( instance->baked_light_sampler_info );
+ instance->baked_light_sampler_info=NULL;
+ }
+
instance->data.morph_values.clear();
}
@@ -1992,6 +2186,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
//instance->portal_info = memnew(Instance::PortalInfo);
//instance->portal_info->portal=portal_owner.get(p_base);
+ } else if (baked_light_sampler_owner.owns(p_base)) {
+
+
+ instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER;
+ instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo);
+ instance->baked_light_sampler_info->sampler=baked_light_sampler_owner.get(p_base);
+
+ //instance->portal_info = memnew(Instance::PortalInfo);
+ //instance->portal_info->portal=portal_owner.get(p_base);
+
} else {
ERR_EXPLAIN("Invalid base RID for instance!")
ERR_FAIL();
@@ -2607,11 +2811,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{
const Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND_V( !instance,RID() );
if (instance->baked_light)
- instance->baked_light->self;
+ return instance->baked_light->self;
return RID();
}
+
+void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) {
+
+ VS_CHANGED;
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->sampled_light) {
+ instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance);
+ instance->data.sampled_light=RID();
+ }
+
+ if(p_baked_light_sampler.is_valid()) {
+ Instance *sampler_instance = instance_owner.get( p_baked_light_sampler );
+ ERR_FAIL_COND( !sampler_instance );
+ ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER );
+ instance->sampled_light=sampler_instance;
+ instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance);
+ } else {
+ instance->sampled_light=NULL;
+ }
+
+ instance->data.sampled_light=RID();
+
+}
+
+RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const {
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND_V( !instance,RID() );
+
+ if (instance->sampled_light)
+ return instance->sampled_light->self;
+ else
+ return RID();
+
+}
+
+
void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){
VS_CHANGED;
@@ -2747,6 +2990,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) {
pairable=true;
}
+ if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) {
+
+ pairable_mask=(1<<INSTANCE_BAKED_LIGHT);
+ pairable=true;
+ }
+
+
if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) {
base_type|=INSTANCE_ROOMLESS_MASK;
@@ -2859,6 +3109,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) {
new_aabb=baked_light->octree_aabb;
} break;
+ case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: {
+
+ BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid );
+ ERR_FAIL_COND(!baked_light_sampler);
+ float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS];
+
+ new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2));
+
+ } break;
+
default: {}
}
@@ -3762,6 +4022,17 @@ void VisualServerRaster::free( RID p_rid ) {
baked_light_owner.free(p_rid);
memdelete(baked_light);
+ } else if (baked_light_sampler_owner.owns(p_rid)) {
+
+ _free_attached_instances(p_rid);
+
+ BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid);
+ ERR_FAIL_COND(!baked_light_sampler);
+ //if (baked_light->data.octree_texture.is_valid())
+ // rasterizer->free(baked_light->data.octree_texture);
+ baked_light_sampler_owner.free(p_rid);
+ memdelete(baked_light_sampler);
+
} else if (camera_owner.owns(p_rid)) {
// delete te camera
@@ -3813,7 +4084,9 @@ void VisualServerRaster::free( RID p_rid ) {
instance_set_room(p_rid,RID());
instance_set_scenario(p_rid,RID());
instance_geometry_set_baked_light(p_rid,RID());
+ instance_geometry_set_baked_light_sampler(p_rid,RID());
instance_set_base(p_rid,RID());
+
if (instance->data.skeleton.is_valid())
instance_attach_skeleton(p_rid,RID());
@@ -4957,6 +5230,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance
//attempt to conncet portal A (will go through B anyway)
//this is a little hackish, but works fine in practice
+ } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) {
+
+ if (B->base_type==INSTANCE_BAKED_LIGHT) {
+ SWAP(A,B);
+ }
+
+ ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL);
+ B->baked_light_sampler_info->baked_lights.insert(A);
+
} else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) {
if (B->base_type==INSTANCE_ROOM)
@@ -5006,6 +5288,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance
self->_portal_attempt_connect(A);
self->_portal_attempt_connect(B);
+ } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) {
+
+ if (B->base_type==INSTANCE_BAKED_LIGHT) {
+ SWAP(A,B);
+ }
+
+ ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER);
+ B->baked_light_sampler_info->baked_lights.erase(A);
+
} else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) {
if (B->base_type==INSTANCE_ROOM)
@@ -5197,6 +5488,308 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance
}
+void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) {
+
+
+ BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler;
+ int res = sampler_opts->resolution;
+ int dp_size = res*res*2;
+ Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors
+ Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals
+ const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr();
+
+
+ if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) {
+ if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) {
+ rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light);
+ }
+
+ p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution;
+ p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2);
+
+
+ }
+
+
+ zeromem(dp_map,sizeof(Color)*dp_size);
+ bool valid=false;
+ int samples=0;
+
+
+ for(Set<Instance*>::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) {
+
+ Instance *bl = E->get();
+ if (bl->baked_light_info->baked_light->sampler.size()==0)
+ continue; //not usable
+
+
+ Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse();
+ for(int i=0;i<dp_size;i++) {
+ dp_normals[i]=norm_xform.xform(dp_src_normals[i]).normalized();
+ }
+
+ //normals in place
+
+
+ //sample octree
+
+ float r = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_RADIUS];
+ float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION];
+ float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH];
+ Vector3 s = p_sampled_light->data.transform.basis.get_scale();
+
+ r*=MAX(MAX(s.x,s.y),s.z);
+ AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2)));
+ //ok got octree local AABB
+
+ DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read();
+ const int *rptr = rp.ptr();
+
+ int first = rptr[1];
+ int depth = rptr[2];
+ bool islinear = rptr[3]&1;
+ depth+=1;
+
+ AABB aabb;
+ aabb.pos.x=decode_float((const uint8_t*)&rptr[4]);
+ aabb.pos.y=decode_float((const uint8_t*)&rptr[5]);
+ aabb.pos.z=decode_float((const uint8_t*)&rptr[6]);
+ aabb.size.x=decode_float((const uint8_t*)&rptr[7]);
+ aabb.size.y=decode_float((const uint8_t*)&rptr[8]);
+ aabb.size.z=decode_float((const uint8_t*)&rptr[9]);
+
+ uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t));
+ int *stack_ptr=(int*)alloca(depth*sizeof(int));
+ AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB));
+
+ stack[0]=0;
+ stack_ptr[0]=first;
+ aabb_stack[0]=aabb;
+ Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5;
+
+
+ int stack_pos=0;
+ Color max_col;
+
+ //int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO];
+
+ int lalimit = sample_aabb.get_longest_axis_index();
+ float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit];
+
+
+ while(true) {
+
+
+ bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0;
+
+ if (aabb_stack[stack_pos].size[lalimit]<limit) {
+ leaf=true;
+ }
+
+
+ if (leaf) {
+
+ Vector3 from = aabb_stack[stack_pos].pos + aabb_stack[stack_pos].size * 0.5;
+ Vector3 norm = (from-center).normalized();
+
+
+ Color col;
+ col.r = ((rptr[ stack_ptr[stack_pos] ]&0xFFFF)/256.0);
+ col.g = ((rptr[ stack_ptr[stack_pos]+1 ]>>16)/256.0);
+ col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0);
+
+
+ max_col.r = MAX(max_col.r,col.r);
+ max_col.g = MAX(max_col.g,col.g);
+ max_col.b = MAX(max_col.b,col.b);
+
+ if (!islinear && p_linear_colorspace) {
+ col=col.to_linear();
+ }
+
+ float distance;
+
+ if (aabb_stack[stack_pos].has_point(center)) {
+ distance=0;
+ } else {
+
+ Vector3 support = aabb_stack[stack_pos].get_support(norm);
+ distance = Math::absf(norm.dot(support)-norm.dot(center));
+
+ }
+
+ if (distance>r)
+ distance=r;
+
+ float mult = powf(1.0-distance/r,att)*str;
+ if (mult>0) {
+ col.r*=mult;
+ col.g*=mult;
+ col.b*=mult;
+
+
+
+ for(int i=0;i<dp_size;i++) {
+ float mult2 = norm.dot(dp_normals[i]);
+ if (mult2<0)
+ mult2=0;
+ Color col2(col.r*mult2,col.g*mult2,col.b*mult2,1.0);
+ dp_map[i].r=MAX(dp_map[i].r,col2.r);
+ dp_map[i].g=MAX(dp_map[i].g,col2.g);
+ dp_map[i].b=MAX(dp_map[i].b,col2.b);
+ }
+
+ }
+
+ samples++;
+ //nothing is valid unless you hit a leaf
+ valid=true;
+ stack_pos--;
+ } else if ((stack[stack_pos]&0xFF)<8) {
+
+ int i = stack[stack_pos]&0xFF;
+ int base = (stack[stack_pos]>>8);
+
+ if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<<i))) {
+ //no bit, no test
+ stack[stack_pos]=(base<<8)+(i+1);
+ continue;
+ }
+
+ stack[stack_pos]=((base+1)<<8)+(i+1);
+
+ AABB child_aabb = aabb_stack[stack_pos];
+ child_aabb.size*=0.5;
+ if (i&1)
+ child_aabb.pos.x+=child_aabb.size.x;
+ if (i&2)
+ child_aabb.pos.y+=child_aabb.size.y;
+ if (i&4)
+ child_aabb.pos.z+=child_aabb.size.z;
+
+ if (!child_aabb.intersects(sample_aabb)) {
+ continue;
+ }
+
+ if (child_aabb.encloses(sample_aabb)) {
+ stack[stack_pos]=(base<<8)|8; //don't test the rest
+ }
+
+ stack_pos++;
+ ERR_FAIL_COND(stack_pos>=depth);
+
+ stack[stack_pos]=0;
+ stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ];
+ aabb_stack[stack_pos]=child_aabb;
+ } else {
+ stack_pos--;
+ if (stack_pos<0)
+ break;
+ }
+ }
+
+
+ }
+
+ //print_line("samples "+itos(samples) );
+
+ if (valid) {
+
+ for(int i=0;i<res;i++) {
+ //average seams to avoid aliasing
+ {
+ //top
+ int ofs1 = i;
+ int ofs2 = dp_size-res+i;
+ Color avg(
+ (dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
+ (dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
+ (dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
+ 1.0
+ );
+ dp_map[ofs1]=avg;
+ dp_map[ofs2]=avg;
+ }
+ {
+ //bottom
+ int ofs1 = res*res-res+i;
+ int ofs2 = res*res+i;
+ Color avg(
+ (dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
+ (dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
+ (dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
+ 1.0
+ );
+ dp_map[ofs1]=avg;
+ dp_map[ofs2]=avg;
+ }
+ {
+ //left
+ int ofs1 = i*res;
+ int ofs2 = res*res+(res-i-1)*res;
+ Color avg(
+ (dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
+ (dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
+ (dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
+ 1.0
+ );
+ dp_map[ofs1]=avg;
+ dp_map[ofs2]=avg;
+ }
+ {
+ //right
+ int ofs1 = i*res+(res-1);
+ int ofs2 = res*res+(res-i-1)*res+(res-1);
+ Color avg(
+ (dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
+ (dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
+ (dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
+ 1.0
+ );
+ dp_map[ofs1]=avg;
+ dp_map[ofs2]=avg;
+ }
+
+ }
+
+ rasterizer->sampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0);
+ for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) {
+
+ F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light;
+ }
+
+
+ } else {
+
+ for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) {
+
+ F->get()->data.sampled_light=RID(); //do not use because nothing close
+ }
+ }
+
+
+
+
+/*
+ highp vec3 vtx = vertex_interp;
+ vtx.z*=dual_paraboloid.y; //side to affect
+ vtx.z+=0.01;
+ dp_clip=vtx.z;
+ highp float len=length( vtx );
+ vtx=normalize(vtx);
+ vtx.xy/=1.0+vtx.z;
+ vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near);
+ vtx+=normalize(vtx)*0.025;
+ vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace
+ vertex_interp=vtx;
+*/
+
+
+
+
+}
+
+
void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) {
@@ -5248,6 +5841,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
/* STEP 2 - CULL */
int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL);
light_cull_count=0;
+ light_samplers_culled=0;
/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
@@ -5408,6 +6002,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
keep=true;
}
+
+
}
@@ -5420,6 +6016,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
cull_range.min=min;
if (max>cull_range.max)
cull_range.max=max;
+
+ if (ins->sampled_light && ins->sampled_light->baked_light_sampler_info->last_pass!=render_pass) {
+ if (light_samplers_culled<MAX_LIGHT_SAMPLERS) {
+ light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light;
+ ins->sampled_light->baked_light_sampler_info->last_pass=render_pass;
+ }
+ }
}
}
@@ -5499,7 +6102,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
}
- {
+ { //this should eventually change to
//assign shadows by distance to camera
SortArray<Instance*,_InstanceLightsort> sorter;
sorter.sort(light_cull_result,light_cull_count);
@@ -5520,10 +6123,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
}
}
+ /* ENVIRONMENT */
-
- /* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/
-
RID environment;
if (p_camera->env.is_valid()) //camera has more environment priority
environment=p_camera->env;
@@ -5532,6 +6133,22 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
else
environment=p_scenario->fallback_environment;
+
+ /* STEP 6 - SAMPLE BAKED LIGHT */
+
+ bool islinear =false;
+ if (environment.is_valid()) {
+ islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB);
+ }
+
+ for(int i=0;i<light_samplers_culled;i++) {
+
+ _process_sampled_light(p_camera->transform,light_sampler_cull_result[i],islinear);
+ }
+
+ /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/
+
+
rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug);
rasterizer->set_viewport(viewport_rect);
@@ -5838,6 +6455,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
desired_rect.x+=p_ofs_x;
desired_rect.y+=p_ofs_y;
+
// if the viewport is different than the actual one, change it
if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x ||
@@ -5847,7 +6465,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
viewport_rect=desired_rect;
- rasterizer->set_viewport(viewport_rect);
+ rasterizer->set_viewport(viewport_rect);
}
@@ -5995,7 +6613,14 @@ void VisualServerRaster::_draw_viewports() {
int window_w = OS::get_singleton()->get_video_mode(E->get()).width;
int window_h = OS::get_singleton()->get_video_mode(E->get()).height;
- _draw_viewport(vp,0,0,window_w,window_h);
+ Rect2 r(0,0,vp->rect.width,vp->rect.height);
+ if (r.size.width==0)
+ r.size.width=window_w;
+ if (r.size.height==0)
+ r.size.height=window_w;
+
+
+ _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height);
}
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 8ed348affa..3064f9ceb0 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer {
MAX_LIGHTS_CULLED=256,
MAX_ROOM_CULL=32,
MAX_EXTERIOR_PORTALS=128,
+ MAX_LIGHT_SAMPLERS=256,
INSTANCE_ROOMLESS_MASK=(1<<20)
@@ -90,12 +91,29 @@ class VisualServerRaster : public VisualServer {
struct BakedLight {
Rasterizer::BakedLightData data;
+ DVector<int> sampler;
AABB octree_aabb;
Size2i octree_tex_size;
+ Size2i light_tex_size;
};
+ struct BakedLightSampler {
+ float params[BAKED_LIGHT_SAMPLER_MAX];
+ int resolution;
+ Vector<Vector3> dp_cache;
+
+ BakedLightSampler() {
+ params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0;
+ params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0;
+ params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0;
+ params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1;
+ resolution=16;
+ }
+ };
+
+ void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp);
struct Camera {
enum Type {
@@ -169,6 +187,7 @@ class VisualServerRaster : public VisualServer {
List<Instance*>::Element *RE;
Instance *baked_light;
List<Instance*>::Element *BLE;
+ Instance *sampled_light;
bool exterior;
uint64_t last_render_pass;
@@ -179,6 +198,8 @@ class VisualServerRaster : public VisualServer {
InstanceSet lights;
bool light_cache_dirty;
+
+
struct RoomInfo {
Transform affine_inverse;
@@ -235,6 +256,23 @@ class VisualServerRaster : public VisualServer {
Transform affine_inverse;
List<Instance*> owned_instances;
};
+
+ struct BakedLightSamplerInfo {
+
+ Set<Instance*> baked_lights;
+ Set<Instance*> owned_instances;
+ BakedLightSampler *sampler;
+ int resolution;
+ Vector<Color> light_bufer;
+ RID sampled_light;
+ uint64_t last_pass;
+ Transform xform; // viewspace normal to lightspace, might not use one.
+ BakedLightSamplerInfo() {
+ sampler=NULL;
+ last_pass=0;
+ resolution=0;
+ }
+ };
struct ParticlesInfo {
@@ -247,6 +285,7 @@ class VisualServerRaster : public VisualServer {
ParticlesInfo *particles_info;
PortalInfo * portal_info;
BakedLightInfo * baked_light_info;
+ BakedLightSamplerInfo * baked_light_sampler_info;
Instance() {
@@ -282,6 +321,8 @@ class VisualServerRaster : public VisualServer {
baked_light=NULL;
baked_light_info=NULL;
+ baked_light_sampler_info=NULL;
+ sampled_light=NULL;
BLE=NULL;
light_cache_dirty=true;
@@ -603,6 +644,9 @@ class VisualServerRaster : public VisualServer {
int exterior_portal_cull_count;
bool exterior_visited;
+ Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS];
+ int light_samplers_culled;
+
Instance *room_cull_result[MAX_ROOM_CULL];
int room_cull_count;
bool room_cull_enabled;
@@ -638,6 +682,7 @@ class VisualServerRaster : public VisualServer {
mutable RID_Owner<Portal> portal_owner;
mutable RID_Owner<BakedLight> baked_light_owner;
+ mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner;
mutable RID_Owner<Camera> camera_owner;
mutable RID_Owner<Viewport> viewport_owner;
@@ -658,6 +703,8 @@ class VisualServerRaster : public VisualServer {
bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to);
void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal);
void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL);
+ void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace);
+
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity);
void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform);
@@ -953,12 +1000,28 @@ public:
virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree);
virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const;
+ virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light);
+ virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const;
+
+ virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler);
+ virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const;
+
virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier);
virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const;
virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id);
virtual void baked_light_clear_lightmaps(RID p_baked_light);
+ /* BAKED LIGHT SAMPLER */
+
+ virtual RID baked_light_sampler_create();
+
+ virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value);
+ virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const;
+
+ virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution);
+ virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const;
+
/* CAMERA API */
virtual RID camera_create();
@@ -1096,6 +1159,9 @@ public:
virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light);
virtual RID instance_geometry_get_baked_light(RID p_instance) const;
+ virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler);
+ virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const;
+
virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id);
virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const;
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 1ad8c85986..a4653b1013 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -909,6 +909,12 @@ public:
FUNC2(baked_light_set_octree,RID,DVector<uint8_t>);
FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID);
+ FUNC2(baked_light_set_light,RID,DVector<uint8_t>);
+ FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID);
+
+ FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&);
+ FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID);
+
FUNC2(baked_light_set_lightmap_multiplier,RID,float);
FUNC1RC(float,baked_light_get_lightmap_multiplier,RID);
@@ -916,6 +922,14 @@ public:
FUNC1(baked_light_clear_lightmaps,RID);
+ FUNC0R(RID,baked_light_sampler_create);
+
+ FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float );
+ FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam );
+
+ FUNC2(baked_light_sampler_set_resolution,RID,int);
+ FUNC1RC(int,baked_light_sampler_get_resolution,RID);
+
/* CAMERA API */
FUNC0R(RID,camera_create);
@@ -1055,6 +1069,9 @@ public:
FUNC2(instance_geometry_set_baked_light,RID, RID );
FUNC1RC(RID,instance_geometry_get_baked_light,RID);
+ FUNC2(instance_geometry_set_baked_light_sampler,RID, RID );
+ FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID);
+
FUNC2(instance_geometry_set_baked_light_texture_index,RID, int);
FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 366758f1d8..ed04b0d09c 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -590,12 +590,35 @@ public:
virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0;
virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0;
+ virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0;
+ virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0;
+
+ virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0;
+ virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0;
+
virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0;
virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0;
virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0;
virtual void baked_light_clear_lightmaps(RID p_baked_light)=0;
+ /* BAKED LIGHT SAMPLER */
+
+ virtual RID baked_light_sampler_create()=0;
+
+ enum BakedLightSamplerParam {
+ BAKED_LIGHT_SAMPLER_RADIUS,
+ BAKED_LIGHT_SAMPLER_STRENGTH,
+ BAKED_LIGHT_SAMPLER_ATTENUATION,
+ BAKED_LIGHT_SAMPLER_DETAIL_RATIO,
+ BAKED_LIGHT_SAMPLER_MAX
+ };
+
+ virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0;
+ virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0;
+
+ virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0;
+ virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0;
/* CAMERA API */
@@ -824,7 +847,8 @@ public:
INSTANCE_ROOM,
INSTANCE_PORTAL,
INSTANCE_BAKED_LIGHT,
-
+ INSTANCE_BAKED_LIGHT_SAMPLER,
+
INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES)
};
@@ -898,9 +922,13 @@ public:
virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0;
virtual RID instance_geometry_get_baked_light(RID p_instance) const=0;
+ virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0;
+ virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0;
+
virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0;
virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0;
+
virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0;
virtual bool instance_light_is_enabled(RID p_instance) const=0;