Browse Source

a ton of bug fixes to the renderer

Juan Linietsky 8 years ago
parent
commit
903a3aa5f0

+ 1 - 6
drivers/gles3/rasterizer_gles3.cpp

@@ -167,7 +167,6 @@ void RasterizerGLES3::initialize() {
 
 void RasterizerGLES3::begin_frame(){
 
-
 	uint64_t tick = OS::get_singleton()->get_ticks_usec();
 
 	double time_total = double(tick)/1000000.0;
@@ -186,12 +185,8 @@ void RasterizerGLES3::begin_frame(){
 	storage->frame.prev_tick=tick;
 
 
+	storage->update_dirty_resources();
 
-	storage->update_dirty_multimeshes();
-	storage->update_dirty_skeletons();
-	storage->update_dirty_shaders();
-	storage->update_dirty_materials();
-	storage->update_particles();
 
 	storage->info.render_object_count=0;
 	storage->info.render_material_switch_count=0;

+ 12 - 6
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -1387,6 +1387,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
 			int amount = MAX(multi_mesh->size,multi_mesh->visible_instances);
 
 
+
 			if (s->index_array_len>0) {
 
 				glDrawElementsInstanced(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0,amount);
@@ -1610,6 +1611,7 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform&
 		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
 		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds);
 		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER1, gipi->probe?gipi->probe->dynamic_range*gipi->probe->energy:0.0);
+		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS1, gipi->probe?gipi->probe->bias:0.0);
 		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe?!gipi->probe->interior:false);
 		state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache);
 		if (gi_probe_count>1) {
@@ -1622,6 +1624,7 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform&
 			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds);
 			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache);
 			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER2, gipi2->probe?gipi2->probe->dynamic_range*gipi2->probe->energy:0.0);
+			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS2, gipi2->probe?gipi2->probe->bias:0.0);
 			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe?!gipi2->probe->interior:false);
 			state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true );
 		} else {
@@ -1939,6 +1942,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
 
 		if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) {
 
+
 			_setup_geometry(e);
 			storage->info.render_surface_switch_count++;
 
@@ -2881,6 +2885,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_
 				RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getptr(inst->base);
 				ERR_CONTINUE(!multi_mesh);
 
+
 				if (multi_mesh->size==0 || multi_mesh->visible_instances==0)
 					continue;
 
@@ -2896,6 +2901,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_
 					_add_geometry(s,inst,multi_mesh,-1,p_shadow);
 				}
 
+
 			} break;
 			case VS::INSTANCE_IMMEDIATE: {
 
@@ -3777,7 +3783,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 
 	state.used_contact_shadows=true;
 
-	if (storage->frame.current_rt && true) { //detect with state.used_contact_shadows too
+	if ( storage->frame.current_rt && true) { //detect with state.used_contact_shadows too
 		//pre z pass
 
 
@@ -4096,11 +4102,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 
 	if (false && env_radiance_tex) {
 
-			//_copy_texture_to_front_buffer(shadow_atlas->depth);
-			storage->canvas->canvas_begin();
-			glActiveTexture(GL_TEXTURE0);
-			glBindTexture(GL_TEXTURE_2D,env_radiance_tex);
-			storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1));
+		//_copy_texture_to_front_buffer(shadow_atlas->depth);
+		storage->canvas->canvas_begin();
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,env_radiance_tex);
+		storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1));
 
 	}
 

+ 73 - 10
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -2320,6 +2320,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
 		bool is_animated = false;
 
 		if (material->shader && material->shader->mode==VS::SHADER_SPATIAL) {
+
 			if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode==Shader::Spatial::BLEND_MODE_MIX) {
 				can_cast_shadow=true;
 			}
@@ -2332,20 +2333,19 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
 				is_animated=true;
 			}
 
-		}
+			if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) {
+				material->can_cast_shadow_cache=can_cast_shadow;
+				material->is_animated_cache=is_animated;
 
-		if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) {
-			material->can_cast_shadow_cache=can_cast_shadow;
-			material->is_animated_cache=is_animated;
+				for(Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) {
+					E->key()->material_changed_notify();
+				}
 
-			for(Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) {
-				E->key()->material_changed_notify();
-			}
+				for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) {
+					E->key()->base_material_changed();
+				}
 
-			for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) {
-				E->key()->base_material_changed();
 			}
-
 		}
 
 	}
@@ -3619,8 +3619,23 @@ void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh,RID p_mesh){
 	MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
 	ERR_FAIL_COND(!multimesh);
 
+	if (multimesh->mesh.is_valid()) {
+		Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
+		if (mesh) {
+			mesh->multimeshes.remove(&multimesh->mesh_list);
+		}
+	}
+
 	multimesh->mesh=p_mesh;
 
+
+	if (multimesh->mesh.is_valid()) {
+		Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
+		if (mesh) {
+			mesh->multimeshes.add(&multimesh->mesh_list);
+		}
+	}
+
 	multimesh->dirty_aabb=true;
 
 	if (!multimesh->update_list.in_list()) {
@@ -4778,6 +4793,7 @@ RID RasterizerStorageGLES3::gi_probe_create() {
 	gip->dynamic_range=1.0;
 	gip->energy=1.0;
 	gip->propagation=1.0;
+	gip->bias=0.4;
 	gip->interior=false;
 	gip->compress=false;
 	gip->version=1;
@@ -4883,6 +4899,16 @@ void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe,float p_range){
 
 }
 
+
+void RasterizerStorageGLES3::gi_probe_set_bias(RID p_probe,float p_range){
+
+	GIProbe *gip = gi_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!gip);
+
+	gip->bias=p_range;
+
+}
+
 void RasterizerStorageGLES3::gi_probe_set_propagation(RID p_probe,float p_range){
 
 	GIProbe *gip = gi_probe_owner.getornull(p_probe);
@@ -4936,6 +4962,15 @@ float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{
 	return gip->energy;
 }
 
+float RasterizerStorageGLES3::gi_probe_get_bias(RID p_probe) const{
+
+	const GIProbe *gip = gi_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!gip,0);
+
+	return gip->bias;
+}
+
+
 float RasterizerStorageGLES3::gi_probe_get_propagation(RID p_probe) const{
 
 	const GIProbe *gip = gi_probe_owner.getornull(p_probe);
@@ -6265,6 +6300,18 @@ bool RasterizerStorageGLES3::free(RID p_rid){
 		mesh->instance_remove_deps();
 		mesh_clear(p_rid);
 
+		while(mesh->multimeshes.first()) {
+			MultiMesh *multimesh = mesh->multimeshes.first()->self();
+			multimesh->mesh=RID();
+			multimesh->dirty_aabb=true;
+			mesh->multimeshes.remove(mesh->multimeshes.first());
+
+			if (!multimesh->update_list.in_list()) {
+				multimesh_update_list.add(&multimesh->update_list);
+			}
+
+		}
+
 		mesh_owner.free(p_rid);
 		memdelete(mesh);
 
@@ -6274,9 +6321,17 @@ bool RasterizerStorageGLES3::free(RID p_rid){
 		MultiMesh *multimesh = multimesh_owner.get(p_rid);
 		multimesh->instance_remove_deps();
 
+		if (multimesh->mesh.is_valid()) {
+			Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
+			if (mesh) {
+				mesh->multimeshes.remove(&multimesh->mesh_list);
+			}
+		}
+
 		multimesh_allocate(p_rid,0,VS::MULTIMESH_TRANSFORM_2D,VS::MULTIMESH_COLOR_NONE); //frees multimesh
 		update_dirty_multimeshes();
 
+
 		multimesh_owner.free(p_rid);
 		memdelete(multimesh);
 	} else if (immediate_owner.owns(p_rid)) {
@@ -6568,6 +6623,14 @@ void RasterizerStorageGLES3::finalize() {
 
 }
 
+void RasterizerStorageGLES3::update_dirty_resources() {
+
+	update_dirty_multimeshes();
+	update_dirty_skeletons();
+	update_dirty_shaders();
+	update_dirty_materials();
+	update_particles();
+}
 
 RasterizerStorageGLES3::RasterizerStorageGLES3()
 {

+ 20 - 1
drivers/gles3/rasterizer_storage_gles3.h

@@ -567,6 +567,7 @@ public:
 
 		virtual void material_changed_notify() {
 			mesh->instance_material_change_notify();
+			mesh->update_multimeshes();
 		}
 
 		Surface() {
@@ -591,6 +592,7 @@ public:
 		}
 	};
 
+	class MultiMesh;
 
 	struct Mesh : public GeometryOwner {
 
@@ -600,6 +602,17 @@ public:
 		VS::BlendShapeMode blend_shape_mode;
 		Rect3 custom_aabb;
 		mutable uint64_t last_pass;
+		SelfList<MultiMesh>::List multimeshes;
+
+		_FORCE_INLINE_ void update_multimeshes() {
+
+			SelfList<MultiMesh> *mm = multimeshes.first();
+			while(mm) {
+				mm->self()->instance_material_change_notify();
+				mm=mm->next();
+			}
+		}
+
 		Mesh() {
 			blend_shape_mode=VS::BLEND_SHAPE_MODE_NORMALIZED;
 			blend_shape_count=0;
@@ -659,6 +672,7 @@ public:
 		Vector<float> data;
 		Rect3 aabb;
 		SelfList<MultiMesh> update_list;
+		SelfList<MultiMesh> mesh_list;
 		GLuint buffer;
 		int visible_instances;
 
@@ -668,7 +682,7 @@ public:
 		bool dirty_aabb;
 		bool dirty_data;
 
-		MultiMesh() : update_list(this) {
+		MultiMesh() : update_list(this), mesh_list(this) {
 			dirty_aabb=true;
 			dirty_data=true;
 			xform_floats=0;
@@ -921,6 +935,7 @@ public:
 
 		int dynamic_range;
 		float energy;
+		float bias;
 		float propagation;
 		bool interior;
 		bool compress;
@@ -954,6 +969,9 @@ public:
 	virtual void gi_probe_set_energy(RID p_probe,float p_range);
 	virtual float gi_probe_get_energy(RID p_probe) const;
 
+	virtual void gi_probe_set_bias(RID p_probe,float p_range);
+	virtual float gi_probe_get_bias(RID p_probe) const;
+
 	virtual void gi_probe_set_propagation(RID p_probe,float p_range);
 	virtual float gi_probe_get_propagation(RID p_probe) const;
 
@@ -1259,6 +1277,7 @@ public:
 
 	virtual bool has_os_feature(const String& p_feature) const;
 
+	virtual void update_dirty_resources();
 
 	RasterizerStorageGLES3();
 };

+ 12 - 8
drivers/gles3/shaders/scene.glsl

@@ -931,6 +931,7 @@ uniform highp mat4 gi_probe_xform1;
 uniform highp vec3 gi_probe_bounds1;
 uniform highp vec3 gi_probe_cell_size1;
 uniform highp float gi_probe_multiplier1;
+uniform highp float gi_probe_bias1;
 uniform bool gi_probe_blend_ambient1;
 
 uniform mediump sampler3D gi_probe2; //texunit:-7
@@ -938,13 +939,14 @@ uniform highp mat4 gi_probe_xform2;
 uniform highp vec3 gi_probe_bounds2;
 uniform highp vec3 gi_probe_cell_size2;
 uniform highp float gi_probe_multiplier2;
+uniform highp float gi_probe_bias2;
 uniform bool gi_probe2_enabled;
 uniform bool gi_probe_blend_ambient2;
 
-vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance) {
+vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
 
 
-	float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0;
+	float dist = p_bias;//1.0; //dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0;
 	float alpha=0.0;
 	vec3 color = vec3(0.0);
 
@@ -957,12 +959,14 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, b
 		dist += diameter * 0.5;
 	}
 
-	//color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient);
+	if (blend_ambient) {
+		color.rgb = mix(ambient,color.rgb,min(1.0,alpha/0.95));
+	}
 
 	return color;
 }
 
-void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) {
+void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness,float p_bias, out vec4 out_spec, out vec4 out_diff) {
 
 
 
@@ -1023,7 +1027,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
 	for(int i=0;i<MAX_CONE_DIRS;i++) {
 
 		vec3 dir = normalize( (probe_xform * vec4(pos + normal_mtx * cone_dirs[i],1.0)).xyz - probe_pos);
-		light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,ambient,blend_ambient,dir,cone_angle_tan,max_distance);
+		light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,ambient,blend_ambient,dir,cone_angle_tan,max_distance,p_bias);
 
 	}
 
@@ -1033,7 +1037,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
 
 	//irradiance
 
-	vec3 irr_light =  voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,ref_vec,max(min_ref_tan,tan(roughness * 0.5 * M_PI)) ,max_distance);
+	vec3 irr_light =  voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,ref_vec,max(min_ref_tan,tan(roughness * 0.5 * M_PI)) ,max_distance,p_bias);
 
 	irr_light *= multiplier;
 	//irr_light=vec3(0.0);
@@ -1064,11 +1068,11 @@ void gi_probes_compute(vec3 pos, vec3 normal, float roughness, vec3 specular, in
 
 	out_specular = vec3(0.0);
 
-	gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,ambient,environment,gi_probe_blend_ambient1,gi_probe_multiplier1,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
+	gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,ambient,environment,gi_probe_blend_ambient1,gi_probe_multiplier1,normal_mat,ref_vec,roughness,gi_probe_bias1,spec_accum,diff_accum);
 
 	if (gi_probe2_enabled) {
 
-		gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,ambient,environment,gi_probe_blend_ambient2,gi_probe_multiplier2,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
+		gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,ambient,environment,gi_probe_blend_ambient2,gi_probe_multiplier2,normal_mat,ref_vec,roughness,gi_probe_bias2,spec_accum,diff_accum);
 	}
 
 	if (diff_accum.a>0.0) {

+ 67 - 34
scene/3d/gi_probe.cpp

@@ -64,6 +64,19 @@ float GIProbeData::get_energy() const{
 
 }
 
+
+void GIProbeData::set_bias(float p_range) {
+
+	VS::get_singleton()->gi_probe_set_bias(probe,p_range);
+}
+
+float GIProbeData::get_bias() const{
+
+	return VS::get_singleton()->gi_probe_get_bias(probe);
+
+}
+
+
 void GIProbeData::set_propagation(float p_range) {
 
 	VS::get_singleton()->gi_probe_set_propagation(probe,p_range);
@@ -133,6 +146,9 @@ void GIProbeData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_energy","energy"),&GIProbeData::set_energy);
 	ClassDB::bind_method(D_METHOD("get_energy"),&GIProbeData::get_energy);
 
+	ClassDB::bind_method(D_METHOD("set_bias","bias"),&GIProbeData::set_bias);
+	ClassDB::bind_method(D_METHOD("get_bias"),&GIProbeData::get_bias);
+
 	ClassDB::bind_method(D_METHOD("set_propagation","propagation"),&GIProbeData::set_propagation);
 	ClassDB::bind_method(D_METHOD("get_propagation"),&GIProbeData::get_propagation);
 
@@ -149,6 +165,7 @@ void GIProbeData::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY,"dynamic_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_dynamic_data","get_dynamic_data");
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_dynamic_range","get_dynamic_range");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_energy","get_energy");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_bias","get_bias");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"propagation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_propagation","get_propagation");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"interior",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_interior","is_interior");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"compress",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_compress","is_compressed");
@@ -230,6 +247,18 @@ float GIProbe::get_energy() const {
 	return energy;
 }
 
+void GIProbe::set_bias(float p_bias) {
+
+	bias=p_bias;
+	if (probe_data.is_valid()) {
+		probe_data->set_bias(bias);
+	}
+}
+float GIProbe::get_bias() const {
+
+	return bias;
+}
+
 void GIProbe::set_propagation(float p_propagation) {
 
 	propagation=p_propagation;
@@ -466,7 +495,8 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
 		int closest_axis;
 		float closest_dot;
 
-		Vector3 normal = Plane(p_vtx[0],p_vtx[1],p_vtx[2]).normal;
+		Plane plane = Plane(p_vtx[0],p_vtx[1],p_vtx[2]);
+		Vector3 normal = plane.normal;
 
 		for(int i=0;i<3;i++) {
 
@@ -479,6 +509,7 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
 			}
 		}
 
+
 		Vector3 axis;
 		axis[closest_axis]=1.0;
 		Vector3 t1;
@@ -517,30 +548,23 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
 				Vector3 ray_from = from + (t1+t2)*0.5 - axis * p_aabb.size[closest_axis];
 				Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis]*2;
 
+				if (normal.dot(ray_from-ray_to)<0) {
+					SWAP(ray_from,ray_to);
+				}
+
 				Vector3 intersection;
 
-				if (!Geometry::ray_intersects_triangle(ray_from,ray_to,p_vtx[0],p_vtx[1],p_vtx[2],&intersection)) {
-					//no intersect? look in edges
-
-					float closest_dist=1e20;
-					for(int j=0;j<3;j++) {
-						Vector3 c;
-						Vector3 inters;
-						Geometry::get_closest_points_between_segments(p_vtx[j],p_vtx[(j+1)%3],ray_from,ray_to,inters,c);
-						if (c==inters) {
-							closest_dist=0;
-							intersection=inters;
-
-						} else {
-							float d=c.distance_to(intersection);
-							if (j==0 || d<closest_dist) {
-								closest_dist=d;
-								intersection=inters;
-							}
-						}
+				if (!plane.intersects_segment(ray_from,ray_to,&intersection)) {
+					if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) {
+						intersection = plane.project(ray_from);
+					} else {
+
+						intersection = plane.project(ray_to);
 					}
 				}
 
+				intersection=Face3(p_vtx[0],p_vtx[1],p_vtx[2]).get_closest_point_to(intersection);
+
 				Vector2 uv = get_uv(intersection,p_vtx,p_uv);
 
 
@@ -1245,26 +1269,30 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug){
 
 	}
 
-	Ref<GIProbeData> probe_data;
-	probe_data.instance();
-	probe_data->set_bounds(Rect3(-extents,extents*2.0));
-	probe_data->set_cell_size(baker.po2_bounds.size[longest_axis]/baker.axis_cell_size[longest_axis]);
-	probe_data->set_dynamic_data(data);
-	probe_data->set_dynamic_range(dynamic_range);
-	probe_data->set_energy(energy);
-	probe_data->set_interior(interior);
-	probe_data->set_compress(compress);
-	probe_data->set_to_cell_xform(baker.to_cell_space);
-
-	set_probe_data(probe_data);
+	if (p_create_visual_debug) {
+		_create_debug_mesh(&baker);
+	} else {
 
+		Ref<GIProbeData> probe_data;
+		probe_data.instance();
+		probe_data->set_bounds(Rect3(-extents,extents*2.0));
+		probe_data->set_cell_size(baker.po2_bounds.size[longest_axis]/baker.axis_cell_size[longest_axis]);
+		probe_data->set_dynamic_data(data);
+		probe_data->set_dynamic_range(dynamic_range);
+		probe_data->set_energy(energy);
+		probe_data->set_bias(bias);
+		probe_data->set_propagation(propagation);
+		probe_data->set_interior(interior);
+		probe_data->set_compress(compress);
+		probe_data->set_to_cell_xform(baker.to_cell_space);
 
-	if (p_create_visual_debug) {
-		//_create_debug_mesh(&baker);
+		set_probe_data(probe_data);
 	}
 
 
 
+
+
 }
 
 
@@ -1436,6 +1464,9 @@ void GIProbe::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_energy","max"),&GIProbe::set_energy);
 	ClassDB::bind_method(D_METHOD("get_energy"),&GIProbe::get_energy);
 
+	ClassDB::bind_method(D_METHOD("set_bias","max"),&GIProbe::set_bias);
+	ClassDB::bind_method(D_METHOD("get_bias"),&GIProbe::get_bias);
+
 	ClassDB::bind_method(D_METHOD("set_propagation","max"),&GIProbe::set_propagation);
 	ClassDB::bind_method(D_METHOD("get_propagation"),&GIProbe::get_propagation);
 
@@ -1454,6 +1485,7 @@ void GIProbe::_bind_methods() {
 	ADD_PROPERTY( PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_RANGE,"1,16,1"),"set_dynamic_range","get_dynamic_range");
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_energy","get_energy");
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"propagation",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_propagation","get_propagation");
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_RANGE,"0,4,0.001"),"set_bias","get_bias");
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior"),"set_interior","is_interior");
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"compress"),"set_compress","is_compressed");
 	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"data",PROPERTY_HINT_RESOURCE_TYPE,"GIProbeData"),"set_probe_data","get_probe_data");
@@ -1471,6 +1503,7 @@ GIProbe::GIProbe() {
 	subdiv=SUBDIV_128;
 	dynamic_range=4;
 	energy=1.0;
+	bias=0.4;
 	propagation=1.0;
 	extents=Vector3(10,10,10);
 	color_scan_cell_width=4;

+ 7 - 0
scene/3d/gi_probe.h

@@ -38,6 +38,9 @@ public:
 	void set_energy(float p_range);
 	float get_energy() const;
 
+	void set_bias(float p_range);
+	float get_bias() const;
+
 	void set_interior(bool p_enable);
 	bool is_interior() const;
 
@@ -137,6 +140,7 @@ private:
 	Vector3 extents;
 	int dynamic_range;
 	float energy;
+	float bias;
 	float propagation;
 	bool interior;
 	bool compress;
@@ -176,6 +180,9 @@ public:
 	void set_energy(float p_energy);
 	float get_energy() const;
 
+	void set_bias(float p_bias);
+	float get_bias() const;
+
 	void set_propagation(float p_propagation);
 	float get_propagation() const;
 

+ 1 - 1
scene/resources/material.cpp

@@ -339,7 +339,7 @@ void FixedSpatialMaterial::_update_shader() {
 		code+="\tROUGHNESS = specular_tex.a * roughness;\n";
 	} else {
 		code+="\tvec4 specular_tex = texture(texture_specular,UV);\n";
-		code+="\tSPECULAR = vec3(metalness * specular_tex.r);\n";
+		code+="\tSPECULAR = vec3(ALBEDO.rgb * metalness * specular_tex.r);\n";
 		code+="\tROUGHNESS = specular_tex.a * roughness;\n";
 	}
 

+ 5 - 0
scene/resources/texture.cpp

@@ -559,6 +559,11 @@ Error StreamTexture::_load_data(const String& p_path,int &tw,int &th,int& flags,
 		int total_size=0;
 
 		for(int i=0;i<mipmaps;i++) {
+
+			if (i>0) {
+				size = f->get_32();
+			}
+
 			PoolVector<uint8_t> pv;
 			pv.resize(size);
 			{

+ 5 - 0
servers/visual/rasterizer.h

@@ -432,6 +432,9 @@ public:
 	virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
 	virtual float gi_probe_get_energy(RID p_probe) const=0;
 
+	virtual void gi_probe_set_bias(RID p_probe,float p_range)=0;
+	virtual float gi_probe_get_bias(RID p_probe) const=0;
+
 	virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0;
 	virtual float gi_probe_get_propagation(RID p_probe) const=0;
 
@@ -519,6 +522,8 @@ public:
 
 	virtual bool has_os_feature(const String& p_feature) const=0;
 
+	virtual void update_dirty_resources()=0;
+
 	static RasterizerStorage*base_signleton;
 	RasterizerStorage();
 	virtual ~RasterizerStorage() {}

+ 3 - 0
servers/visual/visual_server_raster.h

@@ -825,6 +825,9 @@ public:
 	BIND2(gi_probe_set_energy,RID,float)
 	BIND1RC(float,gi_probe_get_energy,RID)
 
+	BIND2(gi_probe_set_bias,RID,float)
+	BIND1RC(float,gi_probe_get_bias,RID)
+
 	BIND2(gi_probe_set_propagation,RID,float)
 	BIND1RC(float,gi_probe_get_propagation,RID)
 

+ 6 - 0
servers/visual/visual_server_scene.cpp

@@ -1556,9 +1556,11 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const
 						cull_count--;
 						SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
 						j--;
+						continue;
 
 					}
 
+
 					instance->transformed_aabb.project_range_in_plane(Plane(z_vec,0),min,max);
 					if (max>z_max)
 						z_max=max;
@@ -3475,6 +3477,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
 				} else if (p_instance->base_type==VS::INSTANCE_MULTIMESH) {
 					RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base);
 					if (mesh.is_valid()) {
+
 						bool cast_shadows=false;
 
 						int sc = VSG::storage->mesh_get_surface_count(mesh);
@@ -3491,6 +3494,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
 								cast_shadows=true;
 								break;
 							}
+
 						}
 
 						if (!cast_shadows) {
@@ -3538,6 +3542,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
 
 void VisualServerScene::update_dirty_instances() {
 
+	VSG::storage->update_dirty_resources();
+
 	while(_instance_update_list.first()) {
 
 		_update_dirty_instance( _instance_update_list.first()->self() );

+ 3 - 0
servers/visual_server.h

@@ -475,6 +475,9 @@ public:
 	virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
 	virtual float gi_probe_get_energy(RID p_probe) const=0;
 
+	virtual void gi_probe_set_bias(RID p_probe,float p_range)=0;
+	virtual float gi_probe_get_bias(RID p_probe) const=0;
+
 	virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0;
 	virtual float gi_probe_get_propagation(RID p_probe) const=0;