summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/visual/rasterizer.h43
-rw-r--r--servers/visual/visual_server_raster.cpp1
-rw-r--r--servers/visual/visual_server_raster.h20
-rw-r--r--servers/visual/visual_server_scene.cpp366
-rw-r--r--servers/visual/visual_server_scene.h48
-rw-r--r--servers/visual/visual_server_viewport.cpp29
-rw-r--r--servers/visual_server.h28
7 files changed, 417 insertions, 118 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 06509c6fd0..0f70b036a6 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -54,7 +54,7 @@ public:
virtual RID environment_create()=0;
virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg)=0;
- virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size)=0;
+ virtual void environment_set_skybox(RID p_env,RID p_skybox)=0;
virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0;
virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0;
virtual void environment_set_bg_energy(RID p_env,float p_energy)=0;
@@ -84,6 +84,7 @@ public:
Vector<RID> materials;
Vector<RID> light_instances;
+ Vector<RID> reflection_probe_instances;
Vector<float> morph_values;
@@ -125,7 +126,19 @@ public:
virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass)=0;
virtual void light_instance_mark_visible(RID p_light_instance)=0;
- virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID p_environment,RID p_shadow_atlas)=0;
+ virtual RID reflection_atlas_create()=0;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas,int p_size)=0;
+ virtual void reflection_atlas_set_subdivision(RID p_ref_atlas,int p_subdiv)=0;
+
+ virtual RID reflection_probe_instance_create(RID p_probe)=0;
+ virtual void reflection_probe_instance_set_transform(RID p_instance,const Transform& p_transform)=0;
+ virtual void reflection_probe_release_atlas_index(RID p_instance)=0;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance)=0;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance)=0;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas)=0;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance)=0;
+
+ virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass)=0;
virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count)=0;
virtual void set_scene_pass(uint64_t p_pass)=0;
@@ -165,6 +178,11 @@ public:
virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const=0;
+ /* SKYBOX API */
+
+ virtual RID skybox_create()=0;
+ virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0;
+
/* SHADER API */
@@ -324,16 +342,27 @@ public:
virtual RID reflection_probe_create()=0;
+ virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode)=0;
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0;
- virtual void reflection_probe_set_clip(RID p_probe, float p_near, float p_far)=0;
- virtual void reflection_probe_set_min_blend_distance(RID p_probe, float p_distance)=0;
+ virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_ambient)=0;
+ virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0;
+ virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0;
virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0;
virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0;
- virtual void reflection_probe_set_enable_parallax_correction(RID p_probe, bool p_enable)=0;
- virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution)=0;
- virtual void reflection_probe_set_hide_skybox(RID p_probe, bool p_hide)=0;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0;
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const=0;
+ virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const=0;
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const=0;
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const=0;
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const=0;
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const=0;
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const=0;
+
/* ROOM API */
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index bbad460f4f..6ba63a7690 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -94,6 +94,7 @@ void VisualServerRaster::draw(){
VSG::rasterizer->begin_frame();
VSG::viewport->draw_viewports();
+ VSG::scene->render_probes();
//_draw_cursors_and_margins();
VSG::rasterizer->end_frame();
//draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame();
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 4d8a46122c..4e9110445b 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -629,7 +629,10 @@ public:
BIND1(texture_set_shrink_all_x2_on_set_data,bool)
BIND1(texture_debug_usage,List<TextureInfo>*)
+ /* SKYBOX API */
+ BIND0R(RID,skybox_create)
+ BIND3(skybox_set_texture,RID,RID,int)
/* SHADER API */
@@ -772,17 +775,19 @@ public:
BIND0R(RID,reflection_probe_create)
+ BIND2(reflection_probe_set_update_mode,RID, ReflectionProbeUpdateMode )
BIND2(reflection_probe_set_intensity,RID, float )
- BIND3(reflection_probe_set_clip,RID, float , float )
- BIND2(reflection_probe_set_min_blend_distance,RID, float )
+ BIND2(reflection_probe_set_interior_ambient,RID, const Color& )
+ BIND2(reflection_probe_set_interior_ambient_energy,RID, float )
+ BIND2(reflection_probe_set_interior_ambient_probe_contribution,RID, float )
+ BIND2(reflection_probe_set_max_distance,RID, float )
BIND2(reflection_probe_set_extents,RID, const Vector3& )
BIND2(reflection_probe_set_origin_offset,RID, const Vector3& )
- BIND2(reflection_probe_set_enable_parallax_correction,RID, bool )
- BIND2(reflection_probe_set_resolution,RID, int )
- BIND2(reflection_probe_set_hide_skybox,RID, bool )
+ BIND2(reflection_probe_set_as_interior,RID, bool )
+ BIND2(reflection_probe_set_enable_box_projection,RID, bool )
+ BIND2(reflection_probe_set_enable_shadows,RID, bool )
BIND2(reflection_probe_set_cull_mask,RID, uint32_t )
-
/* ROOM API */
BIND0R(RID,room_create)
@@ -866,7 +871,7 @@ public:
BIND0R(RID,environment_create)
BIND2(environment_set_background,RID ,EnvironmentBG )
- BIND3(environment_set_skybox,RID,RID ,int )
+ BIND2(environment_set_skybox,RID,RID )
BIND2(environment_set_skybox_scale,RID,float)
BIND2(environment_set_bg_color,RID,const Color& )
BIND2(environment_set_bg_energy,RID,float )
@@ -890,6 +895,7 @@ public:
BIND2(scenario_set_debug,RID,ScenarioDebugMode )
BIND2(scenario_set_environment,RID, RID )
+ BIND3(scenario_set_reflection_atlas_size,RID, int,int )
BIND2(scenario_set_fallback_environment,RID, RID )
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index e214374f4d..74d77c5262 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -103,8 +103,25 @@ void* VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance
geom->lighting_dirty=true;
return E; //this element should make freeing faster
+ } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+
+ InstanceReflectionProbeData::PairInfo pinfo;
+ pinfo.geometry=A;
+ pinfo.L = geom->reflection_probes.push_back(B);
+
+ List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo);
+
+ geom->reflection_dirty=true;
+
+ return E; //this element should make freeing faster
}
+
+
#if 0
if (A->base_type==INSTANCE_PORTAL) {
@@ -189,6 +206,18 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance
geom->lighting_dirty=true;
+ } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+ List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element*>(udata);
+
+ geom->reflection_probes.erase(E->get().L);
+ reflection_probe->geometries.erase(E);
+
+ geom->reflection_dirty=true;
+
}
#if 0
if (A->base_type==INSTANCE_PORTAL) {
@@ -252,6 +281,13 @@ RID VisualServerScene::scenario_create() {
scenario->octree.set_pair_callback(_instance_pair,this);
scenario->octree.set_unpair_callback(_instance_unpair,this);
+ scenario->reflection_probe_shadow_atlas=VSG::scene_render->shadow_atlas_create();
+ VSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas,1024); //make enough shadows for close distance, don't bother with rest
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,0,4);
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,1,4);
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,2,4);
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,3,8);
+ scenario->reflection_atlas=VSG::scene_render->reflection_atlas_create();
return scenario_rid;
}
@@ -281,6 +317,16 @@ void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_
}
+void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv) {
+
+ Scenario *scenario = scenario_owner.get(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas,p_size);
+ VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas,p_subdiv);
+
+
+}
+
/* INSTANCING API */
@@ -343,6 +389,14 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base){
}
VSG::scene_render->free(light->instance);
} break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data);
+ VSG::scene_render->free(reflection_probe->instance);
+ if (reflection_probe->update_list.in_list()) {
+ reflection_probe_render_list.remove(&reflection_probe->update_list);
+ }
+ } break;
}
if (instance->base_data) {
@@ -508,6 +562,14 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base){
InstanceGeometryData *geom = memnew( InstanceGeometryData );
instance->base_data=geom;
} break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+
+ InstanceReflectionProbeData *reflection_probe = memnew( InstanceReflectionProbeData );
+ reflection_probe->owner=instance;
+ instance->base_data=reflection_probe;
+
+ reflection_probe->instance=VSG::scene_render->reflection_probe_instance_create(p_base);
+ } break;
}
@@ -607,6 +669,12 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario){
light->D=NULL;
}
} break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data);
+ VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
+ } break;
+
}
instance->scenario=NULL;
@@ -876,6 +944,15 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
}
+ if (p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE) {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data);
+
+ VSG::scene_render->reflection_probe_instance_set_transform( reflection_probe->instance, p_instance->transform );
+ reflection_probe->reflection_dirty=true;
+
+ }
+
if (p_instance->aabb.has_no_surface())
return;
@@ -970,7 +1047,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
uint32_t pairable_mask=0;
bool pairable=false;
- if (p_instance->base_type == VS::INSTANCE_LIGHT) {
+ if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type==VS::INSTANCE_REFLECTION_PROBE) {
pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK:0;
pairable=true;
@@ -1072,6 +1149,12 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
new_aabb = VSG::storage->light_get_aabb(p_instance->base);
} break;
+ case VisualServer::INSTANCE_REFLECTION_PROBE: {
+
+ new_aabb = VSG::storage->reflection_probe_get_aabb(p_instance->base);
+
+ } break;
+
#if 0
case VisualServer::INSTANCE_ROOM: {
@@ -1129,7 +1212,7 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
-void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camera* p_camera,RID p_shadow_atlas,Scenario* p_scenario,Size2 p_viewport_rect) {
+void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario) {
InstanceLightData * light = static_cast<InstanceLightData*>(p_instance->base_data);
@@ -1138,14 +1221,14 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer
case VS::LIGHT_DIRECTIONAL: {
- float max_distance = p_camera->zfar;
+ float max_distance =p_cam_projection.get_z_far();
float shadow_max = VSG::storage->light_get_param(p_instance->base,VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
if (shadow_max>0) {
max_distance=MIN(shadow_max,max_distance);
}
- max_distance=MAX(max_distance,p_camera->znear+0.001);
+ max_distance=MAX(max_distance,p_cam_projection.get_z_near()+0.001);
- float range = max_distance-p_camera->znear;
+ float range = max_distance-p_cam_projection.get_z_near();
int splits=0;
switch(VSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
@@ -1156,9 +1239,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer
float distances[5];
- distances[0]=p_camera->znear;
+ distances[0]=p_cam_projection.get_z_near();
for(int i=0;i<splits;i++) {
- distances[i+1]=p_camera->znear+VSG::storage->light_get_param(p_instance->base,VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET+i))*range;
+ distances[i+1]=p_cam_projection.get_z_near()+VSG::storage->light_get_param(p_instance->base,VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET+i))*range;
};
distances[splits]=max_distance;
@@ -1172,38 +1255,24 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer
// setup a camera matrix for that range!
CameraMatrix camera_matrix;
- switch(p_camera->type) {
-
- case Camera::ORTHOGONAL: {
-
- camera_matrix.set_orthogonal(
- p_camera->size,
- p_viewport_rect.width / p_viewport_rect.height,
- distances[(i==0 || !overlap )?i:i-1],
- distances[i+1],
- p_camera->vaspect
-
- );
- } break;
- case Camera::PERSPECTIVE: {
+ float aspect = p_cam_projection.get_aspect();
- camera_matrix.set_perspective(
- p_camera->fov,
- p_viewport_rect.width / (float)p_viewport_rect.height,
- distances[(i==0 || !overlap )?i:i-1],
- distances[i+1],
- p_camera->vaspect
+ if (p_cam_orthogonal) {
- );
+ float w,h;
+ p_cam_projection.get_viewport_size(w,h);
+ camera_matrix.set_orthogonal(w,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false);
+ } else {
- } break;
+ float fov = p_cam_projection.get_fov();
+ camera_matrix.set_perspective(fov,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false);
}
//obtain the frustum endpoints
Vector3 endpoints[8]; // frustum plane endpoints
- bool res = camera_matrix.get_endpoints(p_camera->transform,endpoints);
+ bool res = camera_matrix.get_endpoints(p_cam_transform,endpoints);
ERR_CONTINUE(!res);
// obtain the light frustm ranges (given endpoints)
@@ -1459,8 +1528,8 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer
float angle = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE);
CameraMatrix cm;
- cm.set_perspective( 90, 1.0, 0.01, radius );
- print_line("perspective: "+cm);
+ cm.set_perspective( angle, 1.0, 0.01, radius );
+
Vector<Plane> planes = cm.get_projection_planes(p_instance->transform);
int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
@@ -1477,7 +1546,6 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer
}
- print_line("MOMONGO");
VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,p_instance->transform,radius,0,0);
VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,0,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
@@ -1487,26 +1555,13 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camer
}
-
-
-
void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewport_size,RID p_shadow_atlas) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
- Scenario *scenario = scenario_owner.getornull(p_scenario);
-
- render_pass++;
- uint32_t camera_layer_mask=camera->visible_layers;
-
- VSG::scene_render->set_scene_pass(render_pass);
-
-
/* STEP 1 - SETUP CAMERA */
CameraMatrix camera_matrix;
- Transform camera_inverse_xform = camera->transform.affine_inverse();
bool ortho=false;
@@ -1538,16 +1593,36 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
} break;
}
+ _render_scene(camera->transform,camera_matrix,ortho,camera->env,camera->visible_layers,p_scenario,p_shadow_atlas,RID(),-1);
+
+}
+
+
+void VisualServerScene::_render_scene(const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_force_environment,uint32_t p_visible_layers, RID p_scenario,RID p_shadow_atlas,RID p_reflection_probe,int p_reflection_probe_pass) {
+
+
+
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+
+ render_pass++;
+ uint32_t camera_layer_mask=p_visible_layers;
+
+ VSG::scene_render->set_scene_pass(render_pass);
+
// rasterizer->set_camera(camera->transform, camera_matrix,ortho);
- Vector<Plane> planes = camera_matrix.get_projection_planes(camera->transform);
+ Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
- Plane near_plane(camera->transform.origin,-camera->transform.basis.get_axis(2).normalized());
+ Plane near_plane(p_cam_transform.origin,-p_cam_transform.basis.get_axis(2).normalized());
+ float z_far = p_cam_projection.get_z_far();
/* STEP 2 - CULL */
int cull_count = scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL);
light_cull_count=0;
+
+ reflection_probe_cull_count=0;
+
// light_samplers_culled=0;
/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
@@ -1649,7 +1724,6 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
bool keep=false;
-
if ((camera_layer_mask&ins->layer_mask)==0) {
//failure
@@ -1673,6 +1747,36 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
}
+ } else if (ins->base_type==VS::INSTANCE_REFLECTION_PROBE && ins->visible) {
+
+
+ if (ins->visible && reflection_probe_cull_count<MAX_REFLECTION_PROBES_CULLED) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(ins->base_data);
+
+ if (p_reflection_probe!=reflection_probe->instance) {
+ //avoid entering The Matrix
+
+ if (!reflection_probe->geometries.empty()) {
+ //do not add this light if no geometry is affected by it..
+
+ if (reflection_probe->reflection_dirty || VSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) {
+ if (!reflection_probe->update_list.in_list()) {
+ reflection_probe->render_step=0;
+ reflection_probe_render_list.add(&reflection_probe->update_list);
+ }
+
+ reflection_probe->reflection_dirty=false;
+ }
+
+ if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
+ reflection_probe_instance_cull_result[reflection_probe_cull_count]=reflection_probe->instance;
+ reflection_probe_cull_count++;
+ }
+
+ }
+ }
+ }
} else if ((1<<ins->base_type)&VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows!=VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
@@ -1746,6 +1850,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(ins->base_data);
+
if (geom->lighting_dirty) {
int l=0;
//only called when lights AABB enter/exit this geometry
@@ -1761,7 +1866,23 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
geom->lighting_dirty=false;
}
+ if (geom->reflection_dirty) {
+ int l=0;
+ //only called when reflection probe AABB enter/exit this geometry
+ ins->reflection_probe_instances.resize(geom->reflection_probes.size());
+
+ for (List<Instance*>::Element *E=geom->reflection_probes.front();E;E=E->next()) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(E->get()->base_data);
+
+ ins->reflection_probe_instances[l++]=reflection_probe->instance;
+ }
+
+ geom->reflection_dirty=false;
+ }
+
ins->depth = near_plane.distance_to(ins->transform.origin);
+ ins->depth_layer=CLAMP(int(ins->depth*8/z_far),0,7);
}
@@ -1803,7 +1924,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
//check shadow..
- if (light && VSG::storage->light_has_shadow(E->get()->base)) {
+ if (light && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) {
lights_with_shadow[directional_shadow_count++]=E->get();
}
@@ -1817,7 +1938,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
for(int i=0;i<directional_shadow_count;i++) {
- _light_instance_update_shadow(lights_with_shadow[i],camera,p_shadow_atlas,scenario,p_viewport_size);
+ _light_instance_update_shadow(lights_with_shadow[i],p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario);
}
}
@@ -1841,12 +1962,12 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
{ //compute coverage
- Transform cam_xf = camera->transform;
- float zn = camera_matrix.get_z_near();
+ Transform cam_xf = p_cam_transform;
+ float zn = p_cam_projection.get_z_near();
Plane p (cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2) ); //camera near plane
float vp_w,vp_h; //near plane size in screen coordinates
- camera_matrix.get_viewport_size(vp_w,vp_h);
+ p_cam_projection.get_viewport_size(vp_w,vp_h);
switch(VSG::storage->light_get_type(ins->base)) {
@@ -1861,7 +1982,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
ins->transform.origin+cam_xf.basis.get_axis(0)*radius
};
- if (!ortho) {
+ if (!p_cam_orthogonal) {
//if using perspetive, map them to near plane
for(int j=0;j<2;j++) {
if (p.distance_to(points[j]) < 0 ) {
@@ -1895,7 +2016,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
base+cam_xf.basis.get_axis(0)*w
};
- if (!ortho) {
+ if (!p_cam_orthogonal) {
//if using perspetive, map them to near plane
for(int j=0;j<2;j++) {
if (p.distance_to(points[j]) < 0 ) {
@@ -1933,7 +2054,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
if (redraw) {
//must redraw!
- _light_instance_update_shadow(ins,camera,p_shadow_atlas,scenario,p_viewport_size);
+ _light_instance_update_shadow(ins,p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario);
}
}
@@ -1942,8 +2063,8 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
/* ENVIRONMENT */
RID environment;
- if (camera->env.is_valid()) //camera has more environment priority
- environment=camera->env;
+ if (p_force_environment.is_valid()) //camera has more environment priority
+ environment=p_force_environment;
else if (scenario->environment.is_valid())
environment=scenario->environment;
else
@@ -1964,45 +2085,129 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
#endif
/* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/
-#if 0
- // add lights
+ VSG::scene_render->render_scene(p_cam_transform, p_cam_projection,p_cam_orthogonal,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count+directional_light_count,reflection_probe_instance_cull_result,reflection_probe_cull_count,environment,p_shadow_atlas,scenario->reflection_atlas,p_reflection_probe,p_reflection_probe_pass);
- {
- List<RID>::Element *E=p_scenario->directional_lights.front();
+}
- for(;E;E=E->next()) {
- Instance *light = E->get().is_valid()?instance_owner.get(E->get()):NULL;
+bool VisualServerScene::_render_probe_step(Instance* p_instance,int p_step) {
- ERR_CONTINUE(!light);
- if (!light->light_info->enabled)
- continue;
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data);
+ Scenario *scenario = p_instance->scenario;
+ ERR_FAIL_COND_V(!scenario,true);
- rasterizer->add_light(light->light_info->instance);
- light->light_info->last_add_pass=render_pass;
+ if (p_step==0) {
+
+ if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance,scenario->reflection_atlas)) {
+ return true; //sorry, all full :(
}
+ }
- for (int i=0;i<light_cull_count;i++) {
+ if (p_step>=0 && p_step<6) {
- Instance *ins = light_cull_result[i];
- rasterizer->add_light(ins->light_info->instance);
- ins->light_info->last_add_pass=render_pass;
+ static const Vector3 view_normals[6]={
+ Vector3(-1, 0, 0),
+ Vector3(+1, 0, 0),
+ Vector3( 0,-1, 0),
+ Vector3( 0,+1, 0),
+ Vector3( 0, 0,-1),
+ Vector3( 0, 0,+1)
+ };
+
+ Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base);
+ Vector3 origin_offset = VSG::storage->reflection_probe_get_origin_offset(p_instance->base);
+ float max_distance = VSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
+
+
+ Vector3 edge = view_normals[p_step]*extents;
+ float distance = ABS(view_normals[p_step].dot(edge)-view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
+
+ max_distance = MAX(max_distance,distance);
+
+
+ //render cubemap side
+ CameraMatrix cm;
+ cm.set_perspective(90,1,0.01,max_distance);
+
+
+ static const Vector3 view_up[6]={
+ Vector3( 0,-1, 0),
+ Vector3( 0,-1, 0),
+ Vector3( 0, 0,-1),
+ Vector3( 0, 0,+1),
+ Vector3( 0,-1, 0),
+ Vector3( 0,-1, 0)
+ };
+
+ Transform local_view;
+ local_view.set_look_at(origin_offset,origin_offset+view_normals[p_step],view_up[p_step]);
+
+ Transform xform = p_instance->transform * local_view;
+
+ RID shadow_atlas;
+
+ if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) {
+
+ shadow_atlas=scenario->reflection_probe_shadow_atlas;
}
+
+ _render_scene(xform,cm,false,RID(),VSG::storage->reflection_probe_get_cull_mask(p_instance->base),p_instance->scenario->self,shadow_atlas,reflection_probe->instance,p_step);
+
+ } else {
+ //do roughness postprocess step until it belives it's done
+ return VSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance);
}
- // add geometry
-#endif
+ return false;
+}
- VSG::scene_render->render_scene(camera->transform, camera_matrix,ortho,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count+directional_light_count,environment,p_shadow_atlas);
+void VisualServerScene::render_probes() {
-}
+ SelfList<InstanceReflectionProbeData> *probe = reflection_probe_render_list.first();
+ bool busy=false;
+ while(probe) {
-void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
+ SelfList<InstanceReflectionProbeData> *next=probe->next();
+ RID base = probe->self()->owner->base;
+ switch(VSG::storage->reflection_probe_get_update_mode(base)) {
+
+ case VS::REFLECTION_PROBE_UPDATE_ONCE: {
+ if (busy) //already rendering something
+ break;
+
+ bool done = _render_probe_step(probe->self()->owner,probe->self()->render_step);
+ if (done) {
+ reflection_probe_render_list.remove(probe);
+ } else {
+ probe->self()->render_step++;
+ }
+
+ busy=true; //do not render another one of this kind
+ } break;
+ case VS::REFLECTION_PROBE_UPDATE_ALWAYS: {
+
+ int step=0;
+ bool done=false;
+ while(!done) {
+ done = _render_probe_step(probe->self()->owner,step);
+ step++;
+ }
+
+ reflection_probe_render_list.remove(probe);
+ } break;
+
+ }
+
+ probe=next;
+ }
+}
+
+void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (p_instance->update_aabb)
_update_instance_aabb(p_instance);
@@ -2114,7 +2319,8 @@ bool VisualServerScene::free(RID p_rid) {
while(scenario->instances.first()) {
instance_set_scenario(scenario->instances.first()->self()->self,RID());
}
-
+ VSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
+ VSG::scene_render->free(scenario->reflection_atlas);
scenario_owner.free(p_rid);
memdelete(scenario);
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index e4f06fee64..0eaad45c97 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -16,8 +16,9 @@ public:
MAX_INSTANCE_CULL=65536,
MAX_LIGHTS_CULLED=4096,
+ MAX_REFLECTION_PROBES_CULLED=4096,
MAX_ROOM_CULL=32,
- MAX_EXTERIOR_PORTALS=128,
+ MAX_EXTERIOR_PORTALS=128,
};
uint64_t render_pass;
@@ -156,6 +157,9 @@ public:
List<Instance*> directional_lights;
RID environment;
RID fallback_environment;
+ RID reflection_probe_shadow_atlas;
+ RID reflection_atlas;
+
SelfList<Instance>::List instances;
@@ -172,6 +176,7 @@ public:
virtual void scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
+ virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv);
/* INSTANCING API */
@@ -288,13 +293,43 @@ public:
bool lighting_dirty;
bool can_cast_shadows;
+ List<Instance*> reflection_probes;
+ bool reflection_dirty;
+
InstanceGeometryData() {
lighting_dirty=false;
+ reflection_dirty=true;
can_cast_shadows=true;
}
};
+ struct InstanceReflectionProbeData : public InstanceBaseData {
+
+
+ Instance *owner;
+
+ struct PairInfo {
+ List<Instance*>::Element *L; //light iterator in geometry
+ Instance *geometry;
+ };
+ List<PairInfo> geometries;
+
+
+ RID instance;
+ bool reflection_dirty;
+ SelfList<InstanceReflectionProbeData> update_list;
+
+ int render_step;
+
+ InstanceReflectionProbeData() : update_list(this) {
+
+ reflection_dirty=true;
+ render_step=-1;
+ }
+ };
+
+ SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
struct InstanceLightData : public InstanceBaseData {
@@ -325,6 +360,8 @@ public:
Instance *light_cull_result[MAX_LIGHTS_CULLED];
RID light_instance_cull_result[MAX_LIGHTS_CULLED];
int light_cull_count;
+ RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
+ int reflection_probe_cull_count;
RID_Owner<Instance> instance_owner;
@@ -366,10 +403,15 @@ public:
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
- _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance,Camera* p_camera,RID p_shadow_atlas,Scenario* p_scenario,Size2 p_viewport_rect);
+ _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario);
- void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+ void _render_scene(const Transform p_cam_transform, const CameraMatrix& p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+
+ void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
void update_dirty_instances();
+
+ bool _render_probe_step(Instance* p_instance,int p_step);
+ void render_probes();
bool free(RID p_rid);
VisualServerScene();
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index 18742aa21d..fa2c461f36 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -520,26 +520,29 @@ void VisualServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_
bool VisualServerViewport::free(RID p_rid) {
- Viewport * viewport = viewport_owner.getornull(p_rid);
- if (!viewport)
- return false;
+ if (viewport_owner.owns(p_rid)) {
+ Viewport * viewport = viewport_owner.getornull(p_rid);
- VSG::storage->free( viewport->render_target );
- VSG::scene_render->free( viewport->shadow_atlas );
- while(viewport->canvas_map.front()) {
- viewport_remove_canvas(p_rid,viewport->canvas_map.front()->key());
- }
+ VSG::storage->free( viewport->render_target );
+ VSG::scene_render->free( viewport->shadow_atlas );
+
+ while(viewport->canvas_map.front()) {
+ viewport_remove_canvas(p_rid,viewport->canvas_map.front()->key());
+ }
- viewport_set_scenario(p_rid,RID());
- active_viewports.erase(viewport);
+ viewport_set_scenario(p_rid,RID());
+ active_viewports.erase(viewport);
+
+ viewport_owner.free(p_rid);
+ memdelete(viewport);
- viewport_owner.free(p_rid);
- memdelete(viewport);
+ return true;
+ }
- return true;
+ return false;
}
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 148d090a07..5e318a4fe8 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -127,8 +127,6 @@ public:
virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0;
- virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const=0;
-
struct TextureInfo {
RID texture;
Size2 size;
@@ -139,6 +137,10 @@ public:
virtual void texture_debug_usage(List<TextureInfo> *r_info)=0;
+ /* SKYBOX API */
+
+ virtual RID skybox_create()=0;
+ virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0;
/* SHADER API */
@@ -406,14 +408,23 @@ public:
virtual RID reflection_probe_create()=0;
+ enum ReflectionProbeUpdateMode {
+ REFLECTION_PROBE_UPDATE_ONCE,
+ REFLECTION_PROBE_UPDATE_ALWAYS,
+ };
+
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode)=0;
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0;
- virtual void reflection_probe_set_clip(RID p_probe, float p_near, float p_far)=0;
- virtual void reflection_probe_set_min_blend_distance(RID p_probe, float p_distance)=0;
+ virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_color)=0;
+ virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0;
+ virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0;
virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0;
virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0;
- virtual void reflection_probe_set_enable_parallax_correction(RID p_probe, bool p_enable)=0;
- virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution)=0;
- virtual void reflection_probe_set_hide_skybox(RID p_probe, bool p_hide)=0;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0;
@@ -514,7 +525,7 @@ public:
};
virtual void environment_set_background(RID p_env,EnvironmentBG p_bg)=0;
- virtual void environment_set_skybox(RID p_env,RID p_skybox,int p_radiance_size)=0;
+ virtual void environment_set_skybox(RID p_env,RID p_skybox)=0;
virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0;
virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0;
virtual void environment_set_bg_energy(RID p_env,float p_energy)=0;
@@ -563,6 +574,7 @@ public:
virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0;
+ virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv)=0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0;