diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index cb42790e67c..bf3b902c5cb 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -130,9 +130,9 @@ void RasterizerGLES3::initialize() { ERR_PRINT("Error initializing GLAD"); } -// glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); -// glDebugMessageCallbackARB(_gl_debug_print, NULL); -// glEnable(_EXT_DEBUG_OUTPUT); + glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageCallbackARB(_gl_debug_print, NULL); + glEnable(_EXT_DEBUG_OUTPUT); #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 675b6f228d9..1a63d451b1f 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -100,6 +100,8 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ shadow_atlas->depth=0; shadow_atlas->fbo=0; + + print_line("erasing atlas"); } for(int i=0;i<4;i++) { //clear subdivisions @@ -130,19 +132,18 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - //interpola nearest (though nvidia can improve this) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // Remove artifact on the edges of the shadowmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // We'll use a depth texture to store the depths in the shadow map - // Attach the depth texture to FBO depth attachment point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0); + + glViewport(0,0,shadow_atlas->size,shadow_atlas->size); + glClearDepth(0); + glClear(GL_DEPTH_BUFFER_BIT); + } } @@ -523,12 +524,19 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); + mmsize=reflection_atlas->size; for(int i=0;i<6;i++) { glGenFramebuffers(1, &reflection_atlas->fbo[i]); glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reflection_atlas->color, i); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); + glDisable(GL_SCISSOR_TEST); glViewport(0,0,mmsize,mmsize); glClearColor(0,0,0,0); @@ -538,8 +546,6 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size) } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); } @@ -1020,11 +1026,12 @@ RID RasterizerSceneGLES3::gi_probe_instance_create() { return gi_probe_instance_owner.make_rid(gipi); } -void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe,RID p_data) { +void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) { GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe); ERR_FAIL_COND(!gipi); gipi->data=p_data; + gipi->probe=storage->gi_probe_owner.getornull(p_base); if (p_data.is_valid()) { RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data); ERR_FAIL_COND(!gipd); @@ -1571,6 +1578,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& glBindTexture(GL_TEXTURE_3D,gipi->tex_cache); 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_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) { @@ -1581,7 +1590,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_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_BLEND_AMBIENT2, gipi2->probe?!gipi2->probe->interior:false); state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true ); } else { @@ -4209,7 +4219,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa fbo=shadow_atlas->fbo; vp_height=shadow_atlas->size; - uint32_t key = shadow_atlas->shadow_owners[p_light]; uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3; @@ -4299,24 +4308,22 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa render_list.sort_by_depth(false); //shadow is front to back for performance glDepthMask(true); - glColorMask(0,0,0,0); + glColorMask(1,1,1,1); glDisable(GL_BLEND); glDisable(GL_DITHER); glEnable(GL_DEPTH_TEST); - glBindFramebuffer(GL_FRAMEBUFFER,fbo); if (custom_vp_size) { glViewport(0,0,custom_vp_size,custom_vp_size); glScissor(0,0,custom_vp_size,custom_vp_size); + } else { glViewport(x,y,width,height); glScissor(x,y,width,height); } - //glViewport(x,vp_height-(height+y),width,height); - //glScissor(x,vp_height-(height+y),width,height); glEnable(GL_SCISSOR_TEST); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); @@ -4331,7 +4338,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true); - _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false,false); + _render_list(render_list.elements,render_list.element_count,light_transform,light_projection,0,!flip_facing,false,true,false,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false); state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ce869da131a..31d9964ab00 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -531,6 +531,7 @@ public: struct GIProbeInstance : public RID_Data { RID data; + RasterizerStorageGLES3::GIProbe *probe; GLuint tex_cache; Vector3 cell_size_cache; Vector3 bounds; @@ -542,7 +543,7 @@ public: mutable RID_Owner gi_probe_instance_owner; virtual RID gi_probe_instance_create(); - virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data); + virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data); virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform); virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 9edc37fe3b1..fe8373b20d3 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4695,6 +4695,8 @@ RID RasterizerStorageGLES3::gi_probe_create() { gip->data_depth=0; gip->bounds=AABB(Vector3(),Vector3(1,1,1)); gip->dynamic_range=1.0; + gip->energy=1.0; + gip->interior=false; gip->version=1; gip->cell_size=1.0; @@ -4773,7 +4775,7 @@ DVector RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) cons return gip->dynamic_data; } -void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_range){ +void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,int p_range){ GIProbe *gip = gi_probe_owner.getornull(p_probe); ERR_FAIL_COND(!gip); @@ -4781,7 +4783,7 @@ void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_rang gip->dynamic_range=p_range; } -float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ +int RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ const GIProbe *gip = gi_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!gip,0); @@ -4789,6 +4791,41 @@ float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{ return gip->dynamic_range; } +void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe,float p_range){ + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->energy=p_range; + +} + +void RasterizerStorageGLES3::gi_probe_set_interior(RID p_probe,bool p_enable) { + + GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!gip); + + gip->interior=p_enable; + +} + +bool RasterizerStorageGLES3::gi_probe_is_interior(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,false); + + return gip->interior; + +} + +float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{ + + const GIProbe *gip = gi_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gip,0); + + return gip->energy; +} + void RasterizerStorageGLES3::gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 5d07d0be871..c51cd8d90ba 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -890,7 +890,9 @@ public: Transform to_cell; float cell_size; - float dynamic_range; + int dynamic_range; + float energy; + bool interior; uint32_t version; @@ -921,9 +923,14 @@ public: virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector& p_data); virtual DVector gi_probe_get_dynamic_data(RID p_probe) const; - virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range); - virtual float gi_probe_get_dynamic_range(RID p_probe) const; + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range); + virtual int gi_probe_get_dynamic_range(RID p_probe) const; + 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_interior(RID p_probe,bool p_enable); + virtual bool gi_probe_is_interior(RID p_probe) const; virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth); virtual DVector gi_probe_get_static_data(RID p_gi_probe) const; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index c9de56be4f2..2dfbbd340d9 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -845,14 +845,18 @@ uniform mediump sampler3D gi_probe1; //texunit:-6 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 bool gi_probe_blend_ambient1; uniform mediump sampler3D gi_probe2; //texunit:-7 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 bool gi_probe2_enabled; +uniform bool gi_probe_blend_ambient2; -vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, 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 dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0; @@ -868,10 +872,12 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, dist += diameter * 0.5; } + color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient); + return color.rgb; } -void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, 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, out vec4 out_spec, out vec4 out_diff) { @@ -928,15 +934,19 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s for(int i=0;i0.0) { diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index ce360859d67..93d3e51a8e3 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -53,12 +53,35 @@ DVector GIProbeData::get_dynamic_data() const{ return VS::get_singleton()->gi_probe_get_dynamic_data(probe); } -void GIProbeData::set_dynamic_range(float p_range){ +void GIProbeData::set_dynamic_range(int p_range){ VS::get_singleton()->gi_probe_set_dynamic_range(probe,p_range); } -float GIProbeData::get_dynamic_range() const{ + +void GIProbeData::set_energy(float p_range) { + + VS::get_singleton()->gi_probe_set_energy(probe,p_range); +} + +float GIProbeData::get_energy() const{ + + return VS::get_singleton()->gi_probe_get_energy(probe); + +} + +void GIProbeData::set_interior(bool p_enable) { + + VS::get_singleton()->gi_probe_set_interior(probe,p_enable); + +} + +bool GIProbeData::is_interior() const{ + + return VS::get_singleton()->gi_probe_is_interior(probe); +} + +int GIProbeData::get_dynamic_range() const{ return VS::get_singleton()->gi_probe_get_dynamic_range(probe); @@ -154,15 +177,42 @@ Vector3 GIProbe::get_extents() const { return extents; } -void GIProbe::set_dynamic_range(float p_dynamic_range) { +void GIProbe::set_dynamic_range(int p_dynamic_range) { dynamic_range=p_dynamic_range; } -float GIProbe::get_dynamic_range() const { +int GIProbe::get_dynamic_range() const { return dynamic_range; } +void GIProbe::set_energy(float p_energy) { + + energy=p_energy; + if (probe_data.is_valid()) { + probe_data->set_energy(energy); + } +} +float GIProbe::get_energy() const { + + return energy; +} + +void GIProbe::set_interior(bool p_enable) { + + interior=p_enable; + if (probe_data.is_valid()) { + probe_data->set_interior(p_enable); + } +} + +bool GIProbe::is_interior() const { + + return interior; +} + + + #include "math.h" #define FINDMINMAX(x0,x1,x2,min,max) \ @@ -384,6 +434,8 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V Color albedo_accum; Color emission_accum; + Vector3 normal_accum; + float alpha=0.0; //map to a grid average in the best axis for this face @@ -441,6 +493,9 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V emission_accum.r+=p_material.emission[ofs].r; emission_accum.g+=p_material.emission[ofs].g; emission_accum.b+=p_material.emission[ofs].b; + + normal_accum+=normal; + alpha+=1.0; } @@ -471,6 +526,7 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V emission_accum.g=p_material.emission[ofs].g*alpha; emission_accum.b=p_material.emission[ofs].b*alpha; + normal_accum*=alpha; } else { @@ -486,6 +542,9 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V emission_accum.r*=accdiv; emission_accum.g*=accdiv; emission_accum.b*=accdiv; + + normal_accum*=accdiv; + } //put this temporarily here, corrected in a later step @@ -495,6 +554,9 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V p_baker->bake_cells[p_idx].emission[0]+=emission_accum.r; p_baker->bake_cells[p_idx].emission[1]+=emission_accum.g; p_baker->bake_cells[p_idx].emission[2]+=emission_accum.b; + p_baker->bake_cells[p_idx].normal[0]+=normal_accum.x; + p_baker->bake_cells[p_idx].normal[1]+=normal_accum.y; + p_baker->bake_cells[p_idx].normal[2]+=normal_accum.z; p_baker->bake_cells[p_idx].alpha+=alpha; static const Vector3 side_normals[6]={ @@ -506,11 +568,12 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V Vector3( 0, 0, 1), }; + /* for(int i=0;i<6;i++) { if (normal.dot(side_normals[i])>CMP_EPSILON) { p_baker->bake_cells[p_idx].used_sides|=(1<bake_cells[p_idx].emission[1]/=alpha; p_baker->bake_cells[p_idx].emission[2]/=alpha; + p_baker->bake_cells[p_idx].normal[0]/=alpha; + p_baker->bake_cells[p_idx].normal[1]/=alpha; + p_baker->bake_cells[p_idx].normal[2]/=alpha; + + Vector3 n(p_baker->bake_cells[p_idx].normal[0],p_baker->bake_cells[p_idx].normal[1],p_baker->bake_cells[p_idx].normal[2]); + if (n.length()<0.01) { + //too much fight over normal, zero it + p_baker->bake_cells[p_idx].normal[0]=0; + p_baker->bake_cells[p_idx].normal[1]=0; + p_baker->bake_cells[p_idx].normal[2]=0; + } else { + n.normalize(); + p_baker->bake_cells[p_idx].normal[0]=n.x; + p_baker->bake_cells[p_idx].normal[1]=n.y; + p_baker->bake_cells[p_idx].normal[2]=n.z; + } + + p_baker->bake_cells[p_idx].alpha=1.0; + /* //remove neighbours from used sides for(int n=0;n<6;n++) { @@ -653,6 +735,7 @@ void GIProbe::_fixup_plot(int p_idx, int p_level,int p_x,int p_y, int p_z,Baker p_baker->bake_cells[p_idx].used_sides&=~(1<bake_cells[p_idx].emission[0]=0; p_baker->bake_cells[p_idx].emission[1]=0; p_baker->bake_cells[p_idx].emission[2]=0; + p_baker->bake_cells[p_idx].normal[0]=0; + p_baker->bake_cells[p_idx].normal[1]=0; + p_baker->bake_cells[p_idx].normal[2]=0; p_baker->bake_cells[p_idx].albedo[0]=0; p_baker->bake_cells[p_idx].albedo[1]=0; p_baker->bake_cells[p_idx].albedo[2]=0; @@ -1024,7 +1110,21 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug){ w32[ofs++]=em; } - w32[ofs++]=baker.bake_cells[i].used_sides; + //w32[ofs++]=baker.bake_cells[i].used_sides; + { //normal + + Vector3 n(baker.bake_cells[i].normal[0],baker.bake_cells[i].normal[1],baker.bake_cells[i].normal[2]); + n=n*Vector3(0.5,0.5,0.5)+Vector3(0.5,0.5,0.5); + uint32_t norm=0; + + + norm|=uint32_t(CLAMP( n.x*255.0, 0, 255))<<16; + norm|=uint32_t(CLAMP( n.y*255.0, 0, 255))<<8; + norm|=uint32_t(CLAMP( n.z*255.0, 0, 255))<<0; + + w32[ofs++]=norm; + } + w32[ofs++]=uint32_t(baker.bake_cells[i].alpha*65535.0); } @@ -1036,6 +1136,9 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug){ probe_data->set_bounds(AABB(-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_to_cell_xform(baker.to_cell_space); set_probe_data(probe_data); @@ -1212,13 +1315,21 @@ void GIProbe::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_dynamic_range","max"),&GIProbe::set_dynamic_range); ObjectTypeDB::bind_method(_MD("get_dynamic_range"),&GIProbe::get_dynamic_range); + ObjectTypeDB::bind_method(_MD("set_energy","max"),&GIProbe::set_energy); + ObjectTypeDB::bind_method(_MD("get_energy"),&GIProbe::get_energy); + + ObjectTypeDB::bind_method(_MD("set_interior","enable"),&GIProbe::set_interior); + ObjectTypeDB::bind_method(_MD("is_interior"),&GIProbe::is_interior); + ObjectTypeDB::bind_method(_MD("bake","from_node","create_visual_debug"),&GIProbe::bake,DEFVAL(Variant()),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("debug_bake"),&GIProbe::_debug_bake); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("debug_bake"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ADD_PROPERTY( PropertyInfo(Variant::INT,"subdiv",PROPERTY_HINT_ENUM,"64,128,256,512"),_SCS("set_subdiv"),_SCS("get_subdiv")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"extents"),_SCS("set_extents"),_SCS("get_extents")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"dynamic_range",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("set_dynamic_range"),_SCS("get_dynamic_range")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_RANGE,"1,16,1"),_SCS("set_dynamic_range"),_SCS("get_dynamic_range")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_energy"),_SCS("get_energy")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior"),_SCS("set_interior"),_SCS("is_interior")); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"data",PROPERTY_HINT_RESOURCE_TYPE,"GIProbeData"),_SCS("set_probe_data"),_SCS("get_probe_data")); @@ -1232,10 +1343,12 @@ void GIProbe::_bind_methods() { GIProbe::GIProbe() { subdiv=SUBDIV_128; - dynamic_range=1.0; + dynamic_range=4; + energy=1.0; extents=Vector3(10,10,10); color_scan_cell_width=4; bake_texture_size=128; + interior=false; gi_probe = VS::get_singleton()->gi_probe_create(); diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index e2017acfc3c..297672198cb 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -31,8 +31,14 @@ public: void set_dynamic_data(const DVector& p_data); DVector get_dynamic_data() const; - void set_dynamic_range(float p_range); - float get_dynamic_range() const; + void set_dynamic_range(int p_range); + int get_dynamic_range() const; + + void set_energy(float p_range); + float get_energy() const; + + void set_interior(bool p_enable); + bool is_interior() const; void set_static_data(const DVector& p_data,DataFormat p_format,int p_width,int p_height,int p_depth); DVector get_static_data() const; @@ -73,6 +79,7 @@ private: uint32_t childs[8]; float albedo[3]; //albedo in RGB24 float emission[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast) + float normal[3]; uint32_t used_sides; float alpha; //used for upsampling @@ -84,6 +91,7 @@ private: for(int i=0;i<3;i++) { emission[i]=0; albedo[i]=0; + normal[i]=0; } alpha=0; used_sides=0; @@ -126,7 +134,9 @@ private: Subdiv subdiv; Vector3 extents; - float dynamic_range; + int dynamic_range; + float energy; + bool interior; int color_scan_cell_width; int bake_texture_size; @@ -157,8 +167,15 @@ public: void set_extents(const Vector3& p_extents); Vector3 get_extents() const; - void set_dynamic_range(float p_dynamic_range); - float get_dynamic_range() const; + void set_dynamic_range(int p_dynamic_range); + int get_dynamic_range() const; + + void set_energy(float p_energy); + float get_energy() const; + + void set_interior(bool p_enable); + bool is_interior() const; + void bake(Node *p_from_node=NULL,bool p_create_visual_debug=false); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index bd5eb0a4e62..728997e794a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1283,6 +1283,9 @@ bool Viewport::get_clear_on_new_frame() const{ void Viewport::set_shadow_atlas_size(int p_size) { + if (shadow_atlas_size==p_size) + return; + shadow_atlas_size=p_size; VS::get_singleton()->viewport_set_shadow_atlas_size(viewport,p_size); } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 79560f34865..f22b7e04f65 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -149,7 +149,7 @@ public: virtual bool reflection_probe_instance_postprocess_step(RID p_instance)=0; virtual RID gi_probe_instance_create()=0; - virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data)=0; + virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data)=0; virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform)=0; virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds)=0; @@ -418,9 +418,14 @@ public: virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector& p_data)=0; virtual DVector gi_probe_get_dynamic_data(RID p_probe) const=0; - virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range)=0; - virtual float gi_probe_get_dynamic_range(RID p_probe) const=0; + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0; + virtual int gi_probe_get_dynamic_range(RID p_probe) const=0; + 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_interior(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_interior(RID p_probe) const=0; virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth)=0; virtual DVector gi_probe_get_static_data(RID p_gi_probe) const=0; diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 191330c66cd..9dec587d1ed 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -816,8 +816,14 @@ public: BIND2(gi_probe_set_to_cell_xform,RID,const Transform&) BIND1RC(Transform,gi_probe_get_to_cell_xform,RID) - BIND2(gi_probe_set_dynamic_range,RID,float) - BIND1RC(float,gi_probe_get_dynamic_range,RID) + BIND2(gi_probe_set_dynamic_range,RID,int) + BIND1RC(int,gi_probe_get_dynamic_range,RID) + + BIND2(gi_probe_set_energy,RID,float) + BIND1RC(float,gi_probe_get_energy,RID) + + BIND2(gi_probe_set_interior,RID,bool) + BIND1RC(bool,gi_probe_is_interior,RID) BIND2(gi_probe_set_dynamic_data,RID,const DVector& ) BIND1RC( DVector,gi_probe_get_dynamic_data,RID) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 162647e4201..d74f5265e46 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -1641,6 +1641,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const } } + VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,xform,radius,0,i); VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); } @@ -2203,10 +2204,10 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform,const Came } - bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas,light->instance,coverage,light->last_version); if (redraw) { + print_line("redraw shadow"); //must redraw! _light_instance_update_shadow(ins,p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario); } @@ -2407,6 +2408,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { probe->dynamic.probe_data=VSG::storage->gi_probe_dynamic_data_create(header->width,header->height,header->depth); + probe->dynamic.bake_dynamic_range=VSG::storage->gi_probe_get_dynamic_range(p_instance->base); probe->dynamic.mipmaps_3d.clear(); @@ -2443,7 +2445,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { probe->dynamic.light_to_cell_xform=cell_to_xform * p_instance->transform.affine_inverse(); - VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,probe->dynamic.probe_data); + VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,probe->dynamic.probe_data); VSG::scene_render->gi_probe_instance_set_transform_to_data(probe->probe_instance,probe->dynamic.light_to_cell_xform); @@ -2457,7 +2459,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { probe->dynamic.enabled=false; probe->invalid=!data.is_valid(); if (data.is_valid()) { - VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,data); + VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,data); } } @@ -2541,6 +2543,30 @@ uint32_t VisualServerScene::_gi_bake_find_cell(const GIProbeDataCell *cells,int } +static float _get_normal_advance(const Vector3& p_normal ) { + + Vector3 normal = p_normal; + Vector3 unorm = normal.abs(); + + if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) { + // x code + unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ; + } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { + // y code + unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ; + } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { + // z code + unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ; + } else { + // oh-no we messed up code + // has to be + unorm = Vector3( 1.0, 0.0, 0.0 ); + } + + return 1.0/normal.dot(unorm); + +} + void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int leaf_count, const InstanceGIProbeData::LightCache& light_cache,int sign) { @@ -2548,20 +2574,20 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,con int light_g = int(light_cache.color.g * light_cache.energy * 1024.0)*sign; int light_b = int(light_cache.color.b * light_cache.energy * 1024.0)*sign; + float limits[3]={float(header->width),float(header->height),float(header->depth)}; + Plane clip[3]; + int clip_planes=0; + + + switch(light_cache.type) { case VS::LIGHT_DIRECTIONAL: { - float limits[3]={float(header->width),float(header->height),float(header->depth)}; - Plane clip[3]; - int clip_planes=0; float max_len = Vector3(limits[0],limits[1],limits[2]).length()*1.1; Vector3 light_axis = -light_cache.transform.basis.get_axis(2).normalized(); - print_line("transform directional, axis: "+light_axis); - print_line("limits: "+Vector3(limits[0],limits[1],limits[2])); - for(int i=0;i<3;i++) { if (ABS(light_axis[i])= unorm.y) && (unorm.x >= unorm.z) ) { - // x code - unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ; - } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { - // y code - unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ; - } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { - // z code - unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ; - } else { - // oh-no we messed up code - // has to be - unorm = Vector3( 1.0, 0.0, 0.0 ); - } - - distance_adv = 1.0/normal.dot(unorm); - - } + float distance_adv = _get_normal_advance(light_axis); int success_count=0; @@ -2614,8 +2618,19 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,con InstanceGIProbeData::LocalData *light = &local_data[idx]; Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5); + Vector3 norm ( + (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0 + ); + float att = norm.dot(-light_axis); + if (att<0.001) { + //not lighting towards this + continue; + } + Vector3 from = to - max_len * light_axis; for(int j=0;jenergy[0]+=(uint32_t(light_r)*((cell->albedo>>16)&0xFF))>>8; - light->energy[1]+=(uint32_t(light_g)*((cell->albedo>>8)&0xFF))>>8; - light->energy[2]+=(uint32_t(light_b)*((cell->albedo)&0xFF))>>8; - success_count++; + light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0); + light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0); + light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0); + success_count++; } } print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); print_line("valid cells: "+itos(success_count)); + } break; + case VS::LIGHT_OMNI: + case VS::LIGHT_SPOT: { + + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + Vector3 light_pos = light_cache.transform.origin; + Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); + + + float local_radius = light_cache.radius * light_cache.transform.basis.get_axis(2).length(); + + for(int i=0;ipos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5); + Vector3 norm ( + (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0 + ); + + Vector3 light_axis = (to - light_pos).normalized(); + float distance_adv = _get_normal_advance(light_axis); + + float att = norm.dot(-light_axis); + if (att<0.001) { + //not lighting towards this + continue; + } + + { + float d = light_pos.distance_to(to); + if (d+distance_adv > local_radius) + continue; // too far away + + float dt = CLAMP((d+distance_adv)/local_radius,0,1); + att*= pow(1.0-dt,light_cache.attenuation); + } + + + if (light_cache.type==VS::LIGHT_SPOT) { + + float angle = Math::rad2deg(acos(light_axis.dot(spot_axis))); + if (angle > light_cache.spot_angle) + continue; + + float d = CLAMP(angle/light_cache.spot_angle,1,0); + att*= pow(1.0-d,light_cache.spot_attenuation); + + } + + clip_planes=0; + + for(int c=0;c<3;c++) { + + if (ABS(light_axis[c])-distance_adv) { //use this to avoid precision errors + + result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv); + if (result!=0xFFFFFFFF) { + break; + } + + from+=light_axis*distance_adv; + distance-=distance_adv; + } + + if (result==idx) { + //cell hit itself! hooray! + + light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0); + light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0); + light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0); + + } + } + print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + + } break; } } @@ -2760,9 +2889,9 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { uint32_t idx = level_cells[j]; - uint32_t r = local_data[idx].energy[0]>>2; - uint32_t g = local_data[idx].energy[1]>>2; - uint32_t b = local_data[idx].energy[2]>>2; + uint32_t r = (uint32_t(local_data[idx].energy[0])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t g = (uint32_t(local_data[idx].energy[1])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t b = (uint32_t(local_data[idx].energy[2])/probe_data->dynamic.bake_dynamic_range)>>2; uint32_t a = cells[idx].alpha>>8; uint32_t mm_ofs = sizes[0]*sizes[1]*(local_data[idx].pos[2]) + sizes[0]*(local_data[idx].pos[1]) + (local_data[idx].pos[0]); diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 894d3529af5..418e8387bfa 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -432,6 +432,7 @@ public: Vector > level_cell_lists; RID probe_data; bool enabled; + int bake_dynamic_range; Vector< DVector > mipmaps_3d; @@ -536,7 +537,7 @@ public: uint32_t children[8]; uint32_t albedo; uint32_t emission; - uint32_t sides_used; + uint32_t normal; uint32_t alpha; }; @@ -560,7 +561,6 @@ public: _FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv); void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data); - void _bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int p_leaf_count, const InstanceGIProbeData::LightCache& light_cache,int p_sign); void _bake_gi_probe(Instance *p_probe); bool _check_gi_probe(Instance *p_gi_probe); diff --git a/servers/visual_server.h b/servers/visual_server.h index 6f2aa73952e..20fe8e7d765 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -461,8 +461,14 @@ public: virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector& p_data)=0; virtual DVector gi_probe_get_dynamic_data(RID p_probe) const=0; - virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range)=0; - virtual float gi_probe_get_dynamic_range(RID p_probe) const=0; + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0; + virtual int gi_probe_get_dynamic_range(RID p_probe) const=0; + + 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_interior(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_interior(RID p_probe) const=0; enum GIProbeDataFormat { GI_PROBE_DATA_RGBA8,