From e82dc402052a47b44bb3bcf50ee4801257f92778 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 27 Oct 2014 22:54:32 -0300 Subject: [PATCH] -Much improvement to baked light baker -Fixed many bugs in stretch mode -Fixes to camera project and unproject as consequence of the above -added setget to script (documented in script doc) -more fixes to collada exporter for blender --- SConstruct | 1 + core/globals.cpp | 6 +- core/io/config_file.cpp | 7 +- core/math/quick_hull.cpp | 2 +- demos/3d/platformer/tiles.res | Bin 81338 -> 81631 bytes drivers/gles1/rasterizer_gles1.cpp | 19 + drivers/gles1/rasterizer_gles1.h | 11 + drivers/gles2/rasterizer_gles2.cpp | 180 ++++- drivers/gles2/rasterizer_gles2.h | 20 + drivers/gles2/shaders/material.glsl | 44 +- drivers/ogg/SCsub | 3 +- drivers/theora/SCsub | 3 +- drivers/theoraplayer/SCsub | 14 +- drivers/vorbis/SCsub | 6 + drivers/vorbis/audio_stream_ogg_vorbis.cpp | 2 +- modules/gdscript/gd_compiler.cpp | 10 +- modules/gdscript/gd_editor.cpp | 6 +- modules/gdscript/gd_parser.cpp | 143 ++-- modules/gdscript/gd_parser.h | 2 + modules/gdscript/gd_script.cpp | 33 +- modules/gdscript/gd_script.h | 11 +- modules/gdscript/gd_tokenizer.cpp | 4 +- modules/gdscript/gd_tokenizer.h | 1 + modules/gdscript/register_types.cpp | 4 +- modules/gridmap/grid_map.cpp | 2 +- platform/android/export/export.cpp | 35 +- platform/isim/SCsub | 9 +- platform/isim/detect.py | 14 +- platform/windows/detect.py | 2 +- platform/x11/detect.py | 5 + scene/3d/baked_light_instance.cpp | 78 +++ scene/3d/baked_light_instance.h | 42 ++ scene/3d/camera.cpp | 19 +- scene/3d/skeleton.cpp | 16 + scene/3d/skeleton.h | 2 + scene/3d/visual_instance.cpp | 12 +- scene/3d/visual_instance.h | 1 + scene/animation/animation_player.cpp | 2 +- scene/main/scene_main_loop.h | 3 + scene/main/viewport.cpp | 31 +- scene/main/viewport.h | 5 + scene/register_scene_types.cpp | 1 + scene/resources/baked_light.cpp | 94 ++- scene/resources/baked_light.h | 25 + scene/resources/material.cpp | 4 + servers/visual/rasterizer.h | 7 + servers/visual/rasterizer_dummy.cpp | 20 + servers/visual/rasterizer_dummy.h | 11 + servers/visual/visual_server_raster.cpp | 639 +++++++++++++++++- servers/visual/visual_server_raster.h | 66 ++ servers/visual/visual_server_wrap_mt.h | 17 + servers/visual_server.h | 30 +- tools/collada/collada.cpp | 2 + tools/docdump/makemd.py | 2 +- tools/editor/plugins/baked_light_baker.cpp | 622 ++++++++++++----- tools/editor/plugins/baked_light_baker.h | 48 +- .../plugins/baked_light_baker_cmpxchg.cpp | 84 +++ .../plugins/baked_light_editor_plugin.cpp | 18 +- .../plugins/baked_light_editor_plugin.h | 5 + .../editor/plugins/spatial_editor_plugin.cpp | 2 +- .../blender25/io_scene_dae/export_dae.py | 10 +- 61 files changed, 2163 insertions(+), 354 deletions(-) create mode 100644 tools/editor/plugins/baked_light_baker_cmpxchg.cpp diff --git a/SConstruct b/SConstruct index 7589ab3e6c7..fc9c7dca35b 100644 --- a/SConstruct +++ b/SConstruct @@ -99,6 +99,7 @@ opts.Add('vorbis','Build Ogg Vorbis Support: (yes/no)','yes') opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes') opts.Add('squish','Squish BC Texture Compression in editor (yes/no)','yes') opts.Add('theora','Theora Video (yes/no)','yes') +opts.Add('use_theoraplayer_binary', "Use precompiled binaries from libtheoraplayer for ogg/theora/vorbis (yes/no)", "no") opts.Add('freetype','Freetype support in editor','yes') opts.Add('speex','Speex Audio (yes/no)','yes') opts.Add('xml','XML Save/Load support (yes/no)','yes') diff --git a/core/globals.cpp b/core/globals.cpp index 5be53fd8538..94fa331bed3 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -566,9 +566,11 @@ static Variant _decode_variant(const String& p_string) { ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant()); int scode=0; - if (params[0].is_numeric()) + if (params[0].is_numeric()) { scode=params[0].to_int(); - else + if (scode<10) + scode+=KEY_0; + } else scode=find_keycode(params[0]); InputEvent ie; diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 45e8cf69ab2..b707fd9c13f 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -471,9 +471,12 @@ static Variant _decode_variant(const String& p_string) { ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant()); int scode=0; - if (params[0].is_numeric()) + if (params[0].is_numeric()) { scode=params[0].to_int(); - else + if (scode < 10) { + scode=KEY_0+scode; + } + } else scode=find_keycode(params[0]); InputEvent ie; diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 136a103eef6..a417cdaddf2 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -63,7 +63,7 @@ Error QuickHull::build(const Vector& p_points, Geometry::MeshData &r_me Vector3 sp = p_points[i].snapped(0.0001); if (valid_cache.has(sp)) { valid_points[i]=false; - print_line("INVALIDATED: "+itos(i)); + //print_line("INVALIDATED: "+itos(i)); }else { valid_points[i]=true; valid_cache.insert(sp); diff --git a/demos/3d/platformer/tiles.res b/demos/3d/platformer/tiles.res index 53534788a1a3b67debecbffb2e1090d74a873d6e..d4fb779ff11d6b4a643187d6fe8268389113f77e 100644 GIT binary patch delta 22777 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%0DA(a>CqhhKt&Yb=M1& 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 PWq>-QhR`M+^ph-X&f*)ZCDRw0C;d;xV+ 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[p_param]; +} + +/* SAMPLED LIGHT */ + +RID RasterizerGLES1::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void RasterizerGLES1::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + } /*MISC*/ @@ -5559,6 +5571,13 @@ void RasterizerGLES1::free(const RID& p_rid) { environment_owner.free(p_rid); memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); }; } diff --git a/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h index cca953eed0e..0995089dd7f 100644 --- a/drivers/gles1/rasterizer_gles1.h +++ b/drivers/gles1/rasterizer_gles1.h @@ -488,6 +488,13 @@ class RasterizerGLES1 : public Rasterizer { mutable RID_Owner environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -1190,6 +1197,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); + /*MISC*/ diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index d596aad4b94..bb0fd2e5939 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -5108,7 +5108,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { if (li->near_shadow_buffer) { - glActiveTexture(GL_TEXTURE7); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); //if (read_depth_supported) { glBindTexture(GL_TEXTURE_2D,li->near_shadow_buffer->depth); @@ -5119,7 +5119,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,max_texture_units-1); if (shadow_filter==SHADOW_FILTER_ESM) material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER])); @@ -5739,9 +5739,10 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater float twd=(1.0/mm->tw)*4.0; float thd=1.0/mm->th; float parm[3]={0.0,01.0,(1.0f/mm->tw)}; - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glDisableVertexAttribArray(6); glBindTexture(GL_TEXTURE_2D,mm->tex_id); + material_shader.set_uniform(MaterialShaderGLES2::INSTANCE_MATRICES,GL_TEXTURE0+max_texture_units-2); if (s->index_array_len>0) { @@ -6042,7 +6043,7 @@ void RasterizerGLES2::_setup_skeleton(const Skeleton *p_skeleton) { material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON,p_skeleton!=NULL); if (p_skeleton && p_skeleton->tex_id) { - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glBindTexture(GL_TEXTURE_2D,p_skeleton->tex_id); } @@ -6091,7 +6092,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; - + float sampled_light_dp_multiplier=1.0; bool prev_blend=false; glDisable(GL_BLEND); @@ -6110,6 +6111,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool bind_baked_light_octree=false; bool bind_baked_lightmap=false; bool additive=false; + bool bind_dp_sampler=false; if (!shadow) { @@ -6231,6 +6233,22 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false); material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false); + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,false); + + if (e->instance->sampled_light.is_valid()) { + + SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light); + if (sl) { + + baked_light=NULL; //can't mix + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,true); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); + glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture + sampled_light_dp_multiplier=sl->multiplier; + bind_dp_sampler=true; + } + } + if (!additive && baked_light) { @@ -6241,9 +6259,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex=texture_owner.get(baked_light->octree_texture); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } + if (baked_light->light_texture.is_valid()) { + Texture *texl=texture_owner.get(baked_light->light_texture); + if (texl) { + glActiveTexture(GL_TEXTURE0+max_texture_units-4); + glBindTexture(texl->target,texl->tex_id); //bind the light texture + } + } } } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { @@ -6266,7 +6291,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex = texture_owner.get(texid); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } @@ -6342,7 +6367,15 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_SIZE, baked_light->octree_lattice_size); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_DIVIDE, baked_light->octree_lattice_divide); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_STEPS, baked_light->octree_steps); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,max_texture_units-3); + if (baked_light->light_texture.is_valid()) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-4); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->light_tex_pixel_size); + } else { + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-3); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->octree_tex_pixel_size); + } material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_MULTIPLIER,baked_light->texture_multiplier); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_PIX_SIZE,baked_light->octree_tex_pixel_size); @@ -6351,11 +6384,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (bind_baked_lightmap && (baked_light!=prev_baked_light || rebind)) { - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, 5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, max_texture_units-3); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP_MULTIPLIER, baked_light->lightmap_multiplier); } + if (bind_dp_sampler) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER_MULTIPLIER,sampled_light_dp_multiplier); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER,max_texture_units-3); + } _set_cull(e->mirror,p_reverse_cull); @@ -6364,7 +6402,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::CAMERA_INVERSE_TRANSFORM, p_view_transform_inverse); material_shader.set_uniform(MaterialShaderGLES2::PROJECTION_TRANSFORM, p_projection); if (skeleton && use_hw_skeleton_xform) { - //material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,6); + material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,GL_TEXTURE0+max_texture_units-2); material_shader.set_uniform(MaterialShaderGLES2::SKELTEX_PIXEL_SIZE,skeleton->pixel_size); } if (!shadow) { @@ -7098,6 +7136,7 @@ void RasterizerGLES2::end_scene() { _debug_shadows(); } // _debug_luminances(); + _debug_samplers(); } @@ -7498,6 +7537,38 @@ void RasterizerGLES2::_debug_luminances() { } +void RasterizerGLES2::_debug_samplers() { + canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32,false); + canvas_begin(); + glDisable(GL_BLEND); + _set_color_attrib(Color(1,1,1,1)); + canvas_shader.bind(); + + + List samplers; + sampled_light_owner.get_owned_list(&samplers); + + Size2 debug_size(128,128); + Size2 ofs; + + + for (List::Element *E=samplers.front();E;E=E->next()) { + + SampledLight *sl=sampled_light_owner.get(E->get()); + + _debug_draw_shadow(sl->texture, Rect2( ofs, debug_size )); + + ofs.x+=debug_size.x/2; + if ( (ofs.x+debug_size.x) > viewport.width ) { + + ofs.x=0; + ofs.y+=debug_size.y; + } + } + + + +} void RasterizerGLES2::_debug_shadows() { canvas_begin(); @@ -8115,6 +8186,78 @@ Variant RasterizerGLES2::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + + +RID RasterizerGLES2::sampled_light_dp_create(int p_width,int p_height) { + + SampledLight *slight = memnew(SampledLight); + slight->w=p_width; + slight->h=p_height; + slight->multiplier=1.0; + slight->is_float=float_linear_supported; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1,&slight->texture); + glBindTexture(GL_TEXTURE_2D, slight->texture); +// for debug, but glitchy +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // 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); + + + if (slight->is_float) { +#ifdef GLEW_ENABLED + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#endif + } else { + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + } + + return sampled_light_owner.make_rid(slight); +} + +void RasterizerGLES2::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + SampledLight *slight = sampled_light_owner.get(p_sampled_light); + ERR_FAIL_COND(!slight); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, slight->texture); + + if (slight->is_float) { + +#ifdef GLEW_ENABLED + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#else + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#endif + + } else { + //convert to bytes + uint8_t *tex8 = (uint8_t*)alloca(slight->w*slight->h*4); + const float* src=(const float*)p_data; + + for(int i=0;iw*slight->h*4;i++) { + + tex8[i]=Math::fast_ftoi(CLAMP(src[i]*255.0,0.0,255.0)); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_UNSIGNED_BYTE,p_data); + } + + slight->multiplier=p_multiplier; + +} + /*MISC*/ bool RasterizerGLES2::is_texture(const RID& p_rid) const { @@ -8334,6 +8477,13 @@ void RasterizerGLES2::free(const RID& p_rid) { memdelete(render_target->texture_ptr); render_target_owner.free(p_rid); memdelete( render_target ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + glDeleteTextures(1,&sampled_light->texture); + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); }; } @@ -8926,6 +9076,9 @@ void RasterizerGLES2::init() { latc_supported=true; s3tc_srgb_supported=true; use_anisotropic_filter=true; + float_linear_supported=true; + float_supported=true; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level); anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0))); #ifdef OSX_ENABLED @@ -8970,7 +9123,10 @@ void RasterizerGLES2::init() { GLint vtf; glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&vtf); - use_hw_skeleton_xform=vtf>0 && extensions.has("GL_OES_texture_float"); + float_supported = extensions.has("GL_OES_texture_float"); + use_hw_skeleton_xform=vtf>0 && float_supported; + float_linear_supported = extensions.has("GL_OES_texture_float_linear"); + //if (extensions.has("GL_QCOM_tiled_rendering")) // use_hw_skeleton_xform=false; GLint mva; @@ -9008,7 +9164,7 @@ void RasterizerGLES2::init() { - + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units); //read_depth_supported=false; { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index dc2e22d240a..91395054d9a 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -86,6 +86,8 @@ class RasterizerGLES2 : public Rasterizer { bool use_shadow_mapping; bool use_fp16_fb; bool srgb_supported; + bool float_supported; + bool float_linear_supported; ShadowFilterTechnique shadow_filter; @@ -704,6 +706,18 @@ class RasterizerGLES2 : public Rasterizer { mutable RID_Owner environment_owner; + + struct SampledLight { + + int w,h; + GLuint texture; + float multiplier; + bool is_float; + }; + + mutable RID_Owner sampled_light_owner; + + struct ViewportData { //1x1 fbo+texture for storing previous HDR value @@ -801,6 +815,7 @@ class RasterizerGLES2 : public Rasterizer { RID shadow_material; Material *shadow_mat_ptr; + int max_texture_units; GLuint base_framebuffer; GLuint gui_quad_buffer; @@ -1071,6 +1086,8 @@ class RasterizerGLES2 : public Rasterizer { void _debug_draw_shadows_type(Vector& p_shadows,Point2& ofs); void _debug_shadows(); void _debug_luminances(); + void _debug_samplers(); + /***********/ @@ -1531,6 +1548,9 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier); /*MISC*/ diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 44337e11974..7d9aca4b4d9 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -60,7 +60,7 @@ uniform float normal_mult; #ifdef USE_SKELETON attribute vec4 bone_indices; // attrib:6 attribute vec4 bone_weights; // attrib:7 -uniform highp sampler2D skeleton_matrices; // texunit:6 +uniform highp sampler2D skeleton_matrices; uniform highp float skeltex_pixel_size; #endif @@ -76,7 +76,7 @@ attribute highp vec4 instance_row3; // attrib:11 #ifdef USE_TEXTURE_INSTANCING attribute highp vec3 instance_uv; // attrib:6 -uniform highp sampler2D instance_matrices; // texunit:6 +uniform highp sampler2D instance_matrices; #endif @@ -595,8 +595,10 @@ uniform float time; varying highp vec3 ambient_octree_coords; uniform highp float ambient_octree_lattice_size; uniform highp vec2 ambient_octree_pix_size; +uniform highp vec2 ambient_octree_light_pix_size; uniform highp float ambient_octree_lattice_divide; uniform highp sampler2D ambient_octree_tex; +uniform highp sampler2D ambient_octree_light_tex; uniform float ambient_octree_multiplier; uniform int ambient_octree_steps; @@ -609,6 +611,12 @@ uniform float ambient_lightmap_multiplier; #endif +#ifdef ENABLE_AMBIENT_DP_SAMPLER + +uniform highp sampler2D ambient_dp_sampler; +uniform float ambient_dp_sampler_multiplier; + +#endif FRAGMENT_SHADER_GLOBALS @@ -918,12 +926,12 @@ FRAGMENT_SHADER_CODE } //sample color - octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; + octant_uv=(octant_uv+0.5)*ambient_octree_light_pix_size; highp vec3 sub=(mod(ambient_octree_coords,ld)/ld); - octant_uv.xy+=sub.xy*ambient_octree_pix_size.xy; - vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb; - octant_uv.y+=ambient_octree_pix_size.y*2.0; - vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb; + octant_uv.xy+=sub.xy*ambient_octree_light_pix_size.xy; + vec3 col_up=texture2D(ambient_octree_light_tex,octant_uv).rgb; + octant_uv.y+=ambient_octree_light_pix_size.y*2.0; + vec3 col_down=texture2D(ambient_octree_light_tex,octant_uv).rgb; ambientmap_color=mix(col_up,col_down,sub.z)*ambient_octree_multiplier; ambientmap_color*=diffuse.rgb; @@ -934,6 +942,26 @@ FRAGMENT_SHADER_CODE +#ifdef ENABLE_AMBIENT_DP_SAMPLER + + vec3 ambientmap_color = vec3(0.0,0.0,0.0); + + { + + vec3 dp_normal = normalize((vec4(normal,0) * camera_inverse_transform).xyz); + vec2 ambient_uv = (dp_normal.xy / (1.0+abs(dp_normal.z)))*0.5+0.5; //dual paraboloid + ambient_uv.y*=0.5; + if (dp_normal.z<0) { + + ambient_uv.y=(0.5-ambient_uv.y)+0.5; + + } + + ambientmap_color = texture2D(ambient_dp_sampler,ambient_uv ).rgb * ambient_dp_sampler_multiplier; + ambientmap_color*=diffuse.rgb; + } + +#endif @@ -1224,7 +1252,7 @@ LIGHT_SHADER_CODE #endif -#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) +#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) || defined(ENABLE_AMBIENT_DP_SAMPLER) diffuse.rgb+=ambientmap_color; #endif diff --git a/drivers/ogg/SCsub b/drivers/ogg/SCsub index 5cdc3ea1c07..dd598900643 100644 --- a/drivers/ogg/SCsub +++ b/drivers/ogg/SCsub @@ -6,5 +6,6 @@ ogg_sources = [ "ogg/framing.c", ] -env.drivers_sources+=ogg_sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources+=ogg_sources diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub index d3e58382760..ecabce6c9dc 100644 --- a/drivers/theora/SCsub +++ b/drivers/theora/SCsub @@ -32,6 +32,7 @@ sources = [ "theora/video_stream_theora.cpp", ] -env.drivers_sources += sources +if env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index 023b2c928b6..979ff2ed1bd 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -59,7 +59,6 @@ src/YUV/C/yuv420_grey_c.c src/YUV/C/yuv420_yuv_c.c src/YUV/C/yuv420_rgb_c.c src/TheoraVideoFrame.cpp -video_stream_theoraplayer.cpp """) if env["platform"] == "iphone": @@ -79,7 +78,18 @@ if env["platform"] == "android": env_theora.Append(CPPPATH=["#drivers/theoraplayer/include/theoraplayer", "#drivers/theoraplayer/src/YUV", "#drivers/theoraplayer/src/YUV/libyuv/include", "#drivers/theoraplayer/src/Theora", "#drivers/theoraplayer/src/AVFoundation"]) objs = [] -env_theora.add_source_files(objs, sources) + +env_theora.add_source_files(objs, ["video_stream_theoraplayer.cpp"]) + +if env['use_theoraplayer_binary'] == "yes": + if env["platform"] == "iphone": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/ios']) + env.Append(LIBS=['theoraplayer', 'ogg', 'theora', 'tremor']) + if env["platform"] == "windows": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/windows']) + env.Append(LINKFLAGS=['libtheoraplayer_static.lib', 'libogg.lib', 'libtheora.lib', 'libvorbis.lib']) +else: + env_theora.add_source_files(objs, sources) env.drivers_sources += objs diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub index 1c7cccc4271..2c137629ac2 100644 --- a/drivers/vorbis/SCsub +++ b/drivers/vorbis/SCsub @@ -3,6 +3,9 @@ Import('env') sources = [ "vorbis/audio_stream_ogg_vorbis.cpp", +] + +sources_lib = [ "vorbis/analysis.c", #"vorbis/barkmel.c", "vorbis/bitrate.c", @@ -32,3 +35,6 @@ sources = [ env.drivers_sources += sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources_lib + diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index d9b7b1d1614..996f75d1650 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -215,7 +215,7 @@ AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const { bool AudioStreamOGGVorbis::is_playing() const { - return playing; + return playing || (get_total() - get_todo() -1 > 0); } float AudioStreamOGGVorbis::get_pos() const { diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index 45eac234509..4c564682972 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -179,7 +179,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre //static function if (codegen.script->member_indices.has(identifier)) { - int idx = codegen.script->member_indices[identifier]; + int idx = codegen.script->member_indices[identifier].index; return idx|(GDFunction::ADDR_TYPE_MEMBER<member_indices.size(); - p_script->member_indices[name]=new_idx; + //int new_idx = p_script->member_indices.size(); + GDScript::MemberInfo minfo; + minfo.index = p_script->member_indices.size(); + minfo.setter = p_class->variables[i].setter; + minfo.getter = p_class->variables[i].getter; + p_script->member_indices[name]=minfo; p_script->members.insert(name); } diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 9610f9827f8..d1f511b46ed 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -250,12 +250,12 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level,List *p ERR_FAIL_COND( script.is_null() ); - const Map& mi = script->debug_get_member_indices(); + const Map& mi = script->debug_get_member_indices(); - for(const Map::Element *E=mi.front();E;E=E->next()) { + for(const Map::Element *E=mi.front();E;E=E->next()) { p_members->push_back(E->key()); - p_values->push_back( instance->debug_get_member_by_index(E->get())); + p_values->push_back( instance->debug_get_member_by_index(E->get().index)); } } diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 915fb1e60f0..659e19a9d04 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -2376,80 +2376,113 @@ void GDParser::_parse_class(ClassNode *p_class) { member._export.name=member.identifier; tokenizer->advance(); - p_class->variables.push_back(member); + if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) { - if (tokenizer->get_token()!=GDTokenizer::TK_OP_ASSIGN) { +#ifdef DEBUG_ENABLED + int line = tokenizer->get_token_line(); +#endif + tokenizer->advance(); + + Node *subexpr=NULL; + + subexpr = _parse_and_reduce_expression(p_class,false); + if (!subexpr) + return; + + if (autoexport) { + if (subexpr->type==Node::TYPE_ARRAY) { + + member._export.type=Variant::ARRAY; + + } else if (subexpr->type==Node::TYPE_DICTIONARY) { + + member._export.type=Variant::DICTIONARY; + + } else { + + if (subexpr->type!=Node::TYPE_CONSTANT) { + + _set_error("Type-less export needs a constant expression assigned to infer type."); + return; + } + + ConstantNode *cn = static_cast(subexpr); + if (cn->value.get_type()==Variant::NIL) { + + _set_error("Can't accept a null constant expression for infering export type."); + return; + } + member._export.type=cn->value.get_type(); + } + } +#ifdef TOOLS_ENABLED + if (subexpr->type==Node::TYPE_CONSTANT && member._export.type!=Variant::NIL) { + + ConstantNode *cn = static_cast(subexpr); + if (cn->value.get_type()!=Variant::NIL) { + member.default_value=cn->value; + } + } +#endif + + IdentifierNode *id = alloc_node(); + id->name=member.identifier; + + OperatorNode *op = alloc_node(); + op->op=OperatorNode::OP_ASSIGN; + op->arguments.push_back(id); + op->arguments.push_back(subexpr); + +#ifdef DEBUG_ENABLED + NewLineNode *nl = alloc_node(); + nl->line=line; + p_class->initializer->statements.push_back(nl); +#endif + p_class->initializer->statements.push_back(op); + + + + } else { if (autoexport) { _set_error("Type-less export needs a constant expression assigned to infer type."); return; } - break; + } -#ifdef DEBUG_ENABLED - int line = tokenizer->get_token_line(); -#endif - tokenizer->advance(); - Node *subexpr=NULL; + if (tokenizer->get_token()==GDTokenizer::TK_PR_SETGET) { - subexpr = _parse_and_reduce_expression(p_class,false); - if (!subexpr) - return; - if (autoexport) { - if (subexpr->type==Node::TYPE_ARRAY) { + tokenizer->advance(); - p_class->variables[p_class->variables.size()-1]._export.type=Variant::ARRAY; - - } else if (subexpr->type==Node::TYPE_DICTIONARY) { - - p_class->variables[p_class->variables.size()-1]._export.type=Variant::DICTIONARY; - - } else { - - if (subexpr->type!=Node::TYPE_CONSTANT) { - - _set_error("Type-less export needs a constant expression assigned to infer type."); - return; + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { + //just comma means using only getter + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + _set_error("Expected identifier for setter function after 'notify'."); } - ConstantNode *cn = static_cast(subexpr); - if (cn->value.get_type()==Variant::NIL) { + member.setter=tokenizer->get_token_identifier(); - _set_error("Can't accept a null constant expression for infering export type."); - return; + tokenizer->advance(); + } + + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { + //there is a getter + tokenizer->advance(); + + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + _set_error("Expected identifier for getter function after ','."); } - p_class->variables[p_class->variables.size()-1]._export.type=cn->value.get_type(); + + member.getter=tokenizer->get_token_identifier(); + tokenizer->advance(); + } } -#ifdef TOOLS_ENABLED - if (subexpr->type==Node::TYPE_CONSTANT && p_class->variables[p_class->variables.size()-1]._export.type!=Variant::NIL) { - ConstantNode *cn = static_cast(subexpr); - if (cn->value.get_type()!=Variant::NIL) { - p_class->variables[p_class->variables.size()-1].default_value=cn->value; - } - } -#endif - - - - IdentifierNode *id = alloc_node(); - id->name=member.identifier; - - OperatorNode *op = alloc_node(); - op->op=OperatorNode::OP_ASSIGN; - op->arguments.push_back(id); - op->arguments.push_back(subexpr); - -#ifdef DEBUG_ENABLED - NewLineNode *nl = alloc_node(); - nl->line=line; - p_class->initializer->statements.push_back(nl); -#endif - p_class->initializer->statements.push_back(op); + p_class->variables.push_back(member); _end_statement(); diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 50b84d389a7..16a9a852906 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -82,6 +82,8 @@ public: Variant default_value; #endif StringName identifier; + StringName setter; + StringName getter; }; struct Constant { StringName identifier; diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index f0ef69df5b5..b20fc51a037 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -1537,7 +1537,7 @@ void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { _GDScriptMemberSort ms; ERR_CONTINUE(!scr->member_indices.has(E->key())); - ms.index=scr->member_indices[E->key()]; + ms.index=scr->member_indices[E->key()].index; ms.name=E->key(); msort.push_back(ms); @@ -1961,9 +1961,9 @@ const Map& GDScript::debug_get_member_functions() const { StringName GDScript::debug_get_member_by_index(int p_idx) const { - for(const Map::Element *E=member_indices.front();E;E=E->next()) { + for(const Map::Element *E=member_indices.front();E;E=E->next()) { - if (E->get()==p_idx) + if (E->get().index==p_idx) return E->key(); } @@ -2002,11 +2002,18 @@ bool GDInstance::set(const StringName& p_name, const Variant& p_value) { //member { - const Map::Element *E = script->member_indices.find(p_name); + const Map::Element *E = script->member_indices.find(p_name); if (E) { - members[E->get()]=p_value; + members[E->get().index]=p_value; + if (E->get().setter) { + const Variant *val=&p_value; + Variant::CallError err; + call(E->get().setter,&val,1,err); + if (err.error==Variant::CallError::CALL_OK) { + return true; //function exists, call was successful + } + } return true; - } } @@ -2039,9 +2046,16 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const { while(sptr) { { - const Map::Element *E = script->member_indices.find(p_name); + const Map::Element *E = script->member_indices.find(p_name); if (E) { - r_ret=members[E->get()]; + if (E->get().getter) { + Variant::CallError err; + r_ret=const_cast(this)->call(E->get().getter,NULL,0,err); + if (err.error==Variant::CallError::CALL_OK) { + return true; + } + } + r_ret=members[E->get().index]; return true; //index found } @@ -2131,7 +2145,7 @@ void GDInstance::get_property_list(List *p_properties) const { _GDScriptMemberSort ms; ERR_CONTINUE(!sptr->member_indices.has(E->key())); - ms.index=sptr->member_indices[E->key()]; + ms.index=sptr->member_indices[E->key()].index; ms.name=E->key(); msort.push_back(ms); @@ -2441,6 +2455,7 @@ void GDScriptLanguage::get_reserved_words(List *p_words) const { "false" , "tool", "var", + "setget", "pass", "and", "or", diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 6f0c156d2a6..3b183a41b67 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -220,11 +220,18 @@ class GDScript : public Script { bool valid; + struct MemberInfo { + int index; + StringName setter; + StringName getter; + }; friend class GDInstance; friend class GDFunction; friend class GDCompiler; friend class GDFunctions; +friend class GDScriptLanguage; + Variant _static_ref; //used for static call Ref native; Ref base; @@ -234,7 +241,7 @@ friend class GDFunctions; Set members; //members are just indices to the instanced script. Map constants; Map member_functions; - Map member_indices; //members are just indices to the instanced script. + Map member_indices; //members are just indices to the instanced script. Map > subclasses; #ifdef TOOLS_ENABLED @@ -288,7 +295,7 @@ public: bool is_tool() const { return tool; } Ref get_base() const; - const Map& debug_get_member_indices() const { return member_indices; } + const Map& debug_get_member_indices() const { return member_indices; } const Map& debug_get_member_functions() const; //this is debug only StringName debug_get_member_by_index(int p_idx) const; diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 9ccedd34ea8..0fa83b9eb48 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -91,6 +91,7 @@ const char* GDTokenizer::token_names[TK_MAX]={ "tool", "static", "export", +"setget", "const", "var", "preload", @@ -831,6 +832,7 @@ void GDTokenizerText::_advance() { {TK_PR_TOOL,"tool"}, {TK_PR_STATIC,"static"}, {TK_PR_EXPORT,"export"}, + {TK_PR_SETGET,"setget"}, {TK_PR_VAR,"var"}, {TK_PR_PRELOAD,"preload"}, {TK_PR_ASSERT,"assert"}, @@ -1015,7 +1017,7 @@ void GDTokenizerText::advance(int p_amount) { ////////////////////////////////////////////////////////////////////////////////////////////////////// -#define BYTECODE_VERSION 2 +#define BYTECODE_VERSION 3 Error GDTokenizerBuffer::set_code_buffer(const Vector & p_buffer) { diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 1dd538867e9..4f9522fb560 100644 --- a/modules/gdscript/gd_tokenizer.h +++ b/modules/gdscript/gd_tokenizer.h @@ -98,6 +98,7 @@ public: TK_PR_TOOL, TK_PR_STATIC, TK_PR_EXPORT, + TK_PR_SETGET, TK_PR_CONST, TK_PR_VAR, TK_PR_PRELOAD, diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 8b467735029..543eecdf8bd 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -121,16 +121,16 @@ static void register_editor_plugin() { void register_gdscript_types() { + ObjectTypeDB::register_type(); + ObjectTypeDB::register_virtual_type(); script_language_gd=memnew( GDScriptLanguage ); script_language_gd->init(); ScriptServer::register_language(script_language_gd); - ObjectTypeDB::register_type(); resource_loader_gd=memnew( ResourceFormatLoaderGDScript ); ResourceLoader::add_resource_format_loader(resource_loader_gd); resource_saver_gd=memnew( ResourceFormatSaverGDScript ); ResourceSaver::add_resource_format_saver(resource_saver_gd); - ObjectTypeDB::register_virtual_type(); #ifdef TOOLS_ENABLED diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index d258e26a0e2..7c10c474c3f 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -1041,7 +1041,7 @@ void GridMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_clip","enabled","clipabove","floor","axis"),&GridMap::set_clip,DEFVAL(true),DEFVAL(0),DEFVAL(Vector3::AXIS_X)); - ObjectTypeDB::bind_method(_MD("crate_area","id","area"),&GridMap::create_area); + ObjectTypeDB::bind_method(_MD("create_area","id","area"),&GridMap::create_area); ObjectTypeDB::bind_method(_MD("area_get_bounds","area","bounds"),&GridMap::area_get_bounds); ObjectTypeDB::bind_method(_MD("area_set_exterior_portal","area","enable"),&GridMap::area_set_exterior_portal); ObjectTypeDB::bind_method(_MD("area_set_name","area","name"),&GridMap::area_set_name); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index aef223470a5..6bf94b82899 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -184,6 +184,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String cmdline; bool _signed; bool apk_expansion; + bool remove_prev; String apk_expansion_salt; String apk_expansion_pkey; int orientation; @@ -258,7 +259,9 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& String n=p_name; - if (n=="custom_package/debug") + if (n=="one_click_deploy/clear_previous_install") + remove_prev=p_value; + else if (n=="custom_package/debug") custom_debug_package=p_value; else if (n=="custom_package/release") custom_release_package=p_value; @@ -321,7 +324,9 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) const{ String n=p_name; - if (n=="custom_package/debug") + if (n=="one_click_deploy/clear_previous_install") + r_ret=remove_prev; + else if (n=="custom_package/debug") r_ret=custom_debug_package; else if (n=="custom_package/release") r_ret=custom_release_package; @@ -378,6 +383,7 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) void EditorExportPlatformAndroid::_get_property_list( List *p_list) const{ + p_list->push_back( PropertyInfo( Variant::BOOL, "one_click_deploy/clear_previous_install")); p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"apk")); p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"apk")); p_list->push_back( PropertyInfo( Variant::STRING, "command_line/extra_args")); @@ -1448,16 +1454,20 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { return err; } - ep.step("Uninstalling..",1); - - print_line("Uninstalling previous version: "+devices[p_device].name); List args; - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("uninstall"); - args.push_back(package); int rv; - err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); + + if (remove_prev) { + ep.step("Uninstalling..",1); + + print_line("Uninstalling previous version: "+devices[p_device].name); + + args.push_back("-s"); + args.push_back(devices[p_device].id); + args.push_back("uninstall"); + args.push_back(package); + + err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); #if 0 if (err || rv!=0) { EditorNode::add_io_error("Could not install to device."); @@ -1465,6 +1475,8 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { return ERR_CANT_CREATE; } #endif + } + print_line("Installing into device (please wait..): "+devices[p_device].name); ep.step("Installing to Device (please wait..)..",2); @@ -1473,7 +1485,7 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { args.push_back(devices[p_device].id); args.push_back("install"); args.push_back(export_to); - rv; + err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); if (err || rv!=0) { EditorNode::add_io_error("Could not install to device."); @@ -1515,6 +1527,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() { device_lock = Mutex::create(); quit_request=false; orientation=0; + remove_prev=false; device_thread=Thread::create(_device_poll_thread,this); devices_changed=true; diff --git a/platform/isim/SCsub b/platform/isim/SCsub index e7de935b2e0..07761486a9c 100644 --- a/platform/isim/SCsub +++ b/platform/isim/SCsub @@ -34,11 +34,4 @@ if env['ios_appirater'] == "yes": obj = env_ios.Object('#platform/iphone/godot_iphone.cpp') prog = None -if env["target"]=="release": - prog = env_ios.Program('#bin/godot_opt', [obj] + iphone_lib) - #action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM" - #env.AddPostAction(prog, action) -else: - prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) - #action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM" - #env.AddPostAction(prog, action) +prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) diff --git a/platform/isim/detect.py b/platform/isim/detect.py index c89ca81167a..f4a17838f9c 100644 --- a/platform/isim/detect.py +++ b/platform/isim/detect.py @@ -22,7 +22,7 @@ def get_opts(): return [ ('ISIMPLATFORM', 'name of the iphone platform', 'iPhoneSimulator'), ('ISIMPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Platforms/${ISIMPLATFORM}.platform'), - ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}7.0.sdk'), + ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}7.1.sdk'), ('game_center', 'Support for game center', 'yes'), ('store_kit', 'Support for in-app store', 'yes'), ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'), @@ -34,9 +34,7 @@ def get_opts(): def get_flags(): return [ - ('lua', 'no'), ('tools', 'yes'), - ('nedmalloc', 'no'), ('webp', 'yes'), ] @@ -46,10 +44,6 @@ def configure(env): env.Append(CPPPATH=['#platform/iphone']) - env['OBJSUFFIX'] = ".isim.o" - env['LIBSUFFIX'] = ".isim.a" - env['PROGSUFFIX'] = ".isim" - env['ENV']['PATH'] = env['ISIMPATH']+"/Developer/usr/bin/:"+env['ENV']['PATH'] env['CC'] = '$ISIMPATH/Developer/usr/bin/gcc' @@ -83,8 +77,6 @@ def configure(env): env.Append(CCFLAGS=['-O3', '-ffast-math']) env.Append(LINKFLAGS=['-O3', '-ffast-math']) - env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX'] - env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX'] elif (env["target"]=="debug"): @@ -99,8 +91,6 @@ def configure(env): env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6' env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate' - env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fno-exceptions']) + env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fexceptions']) - if env['lua'] == "yes": - env.Append(CCFLAGS=['-DLUA_USE_FLOAT']) diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 63fb5a47a5d..16f70b60d0a 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -64,7 +64,7 @@ def get_flags(): return [ ('freetype','builtin'), #use builtin freetype ('openssl','builtin'), #use builtin openssl - ('theora','no'), #use builtin openssl + ('theora','no'), ] diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 8616a20486f..03de91fa2fb 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -54,6 +54,7 @@ def get_flags(): return [ ('builtin_zlib', 'no'), ("openssl", "yes"), + ("theora","no"), ] @@ -77,6 +78,10 @@ def configure(env): if (env["use_sanitizer"]=="yes"): env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) env.Append(LINKFLAGS=['-fsanitize=address']) + env.extra_suffix=".llvms" + else: + env.extra_suffix=".llvm" + diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index c1cc1f6b685..b55093a7796 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -63,3 +63,81 @@ BakedLightInstance::BakedLightInstance() { } +///////////////////////// + + +void BakedLightSampler::set_param(Param p_param,float p_value) { + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + VS::get_singleton()->baked_light_sampler_set_param(base,VS::BakedLightSamplerParam(p_param),p_value); +} + +float BakedLightSampler::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; + +} + +void BakedLightSampler::set_resolution(int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>32); + resolution=p_resolution; + VS::get_singleton()->baked_light_sampler_set_resolution(base,resolution); +} +int BakedLightSampler::get_resolution() const { + + return resolution; +} + +AABB BakedLightSampler::get_aabb() const { + + float r = get_param(PARAM_RADIUS); + return AABB( Vector3(-r,-r,-r),Vector3(r*2,r*2,r*2)); +} +DVector BakedLightSampler::get_faces(uint32_t p_usage_flags) const { + return DVector(); +} + +void BakedLightSampler::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&BakedLightSampler::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&BakedLightSampler::get_param); + + ObjectTypeDB::bind_method(_MD("set_resolution","resolution"),&BakedLightSampler::set_resolution); + ObjectTypeDB::bind_method(_MD("get_resolution"),&BakedLightSampler::get_resolution); + + + BIND_CONSTANT( PARAM_RADIUS ); + BIND_CONSTANT( PARAM_STRENGTH ); + BIND_CONSTANT( PARAM_ATTENUATION ); + BIND_CONSTANT( PARAM_DETAIL_RATIO ); + BIND_CONSTANT( PARAM_MAX ); + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_RADIUS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_STRENGTH); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); +// ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),_SCS("set_resolution"),_SCS("get_resolution")); + +} + +BakedLightSampler::BakedLightSampler() { + + base = VS::get_singleton()->baked_light_sampler_create(); + set_base(base); + + params[PARAM_RADIUS]=1.0; + params[PARAM_STRENGTH]=1.0; + params[PARAM_ATTENUATION]=1.0; + params[PARAM_DETAIL_RATIO]=0.1; + resolution=16; + + +} + +BakedLightSampler::~BakedLightSampler(){ + + VS::get_singleton()->free(base); +} diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h index b904ced9a7a..0694c813ceb 100644 --- a/scene/3d/baked_light_instance.h +++ b/scene/3d/baked_light_instance.h @@ -30,4 +30,46 @@ public: BakedLightInstance(); }; + + +class BakedLightSampler : public VisualInstance { + OBJ_TYPE(BakedLightSampler,VisualInstance); + + +public: + + enum Param { + PARAM_RADIUS=VS::BAKED_LIGHT_SAMPLER_RADIUS, + PARAM_STRENGTH=VS::BAKED_LIGHT_SAMPLER_STRENGTH, + PARAM_ATTENUATION=VS::BAKED_LIGHT_SAMPLER_ATTENUATION, + PARAM_DETAIL_RATIO=VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + PARAM_MAX=VS::BAKED_LIGHT_SAMPLER_MAX + }; + + + +protected: + + RID base; + float params[PARAM_MAX]; + int resolution; + static void _bind_methods(); +public: + + virtual AABB get_aabb() const; + virtual DVector get_faces(uint32_t p_usage_flags) const; + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + void set_resolution(int p_resolution); + int get_resolution() const; + + BakedLightSampler(); + ~BakedLightSampler(); +}; + +VARIANT_ENUM_CAST( BakedLightSampler::Param ); + + #endif // BAKED_LIGHT_H diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 93a27f7ac14..ab28c0c8d45 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -467,7 +467,15 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } + +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif Vector3 ray; @@ -479,10 +487,9 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); float screen_w,screen_h; cm.get_viewport_size(screen_w,screen_h); - ray=Vector3( ((p_pos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); + ray=Vector3( ((cpos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(cpos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); } - return ray; }; @@ -494,8 +501,14 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); } +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() ); // float aspect = viewport_size.x / viewport_size.y; @@ -505,7 +518,7 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { return get_camera_transform().origin; } else { - Vector2 pos = p_pos / viewport_size; + Vector2 pos = cpos / viewport_size; float vsize,hsize; if (keep_aspect==KEEP_WIDTH) { vsize = size/viewport_size.get_aspect(); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 858ee4e4ad9..737f7d2dced 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -237,6 +237,21 @@ Transform Skeleton::get_bone_transform(int p_bone) const { return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse; } + +void Skeleton::set_bone_global_pose(int p_bone,const Transform& p_pose) { + + ERR_FAIL_INDEX(p_bone,bones.size()); + if (bones[p_bone].parent==-1) { + + set_bone_pose(p_bone,bones[p_bone].rest.inverse() * p_pose); + } else { + + set_bone_pose(p_bone, bones[p_bone].rest.inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); + + } + +} + Transform Skeleton::get_bone_global_pose(int p_bone) const { ERR_FAIL_INDEX_V(p_bone,bones.size(),Transform()); @@ -519,6 +534,7 @@ void Skeleton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose); ObjectTypeDB::bind_method(_MD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose); + ObjectTypeDB::bind_method(_MD("set_bone_global_pose","bone_idx","pose"),&Skeleton::set_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose); diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 3e0ab0afd71..c61946a4c7d 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -118,6 +118,8 @@ public: Transform get_bone_transform(int p_bone) const; Transform get_bone_global_pose(int p_bone) const; + void set_bone_global_pose(int p_bone,const Transform& p_pose); + void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index af535e139fe..398fbdea82c 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -50,17 +50,24 @@ void VisualInstance::_notification(int p_what) { // CHECK ROOM Spatial * parent = get_parent_spatial(); Room *room=NULL; + bool is_geom = cast_to(); while(parent) { room = parent->cast_to(); if (room) break; - else - parent=parent->get_parent_spatial(); + + if (is_geom && parent->cast_to()) { + VS::get_singleton()->instance_geometry_set_baked_light_sampler(get_instance(),parent->cast_to()->get_instance()); + break; + } + + parent=parent->get_parent_spatial(); } + if (room) { VisualServer::get_singleton()->instance_set_room(instance,room->get_instance()); @@ -85,6 +92,7 @@ void VisualInstance::_notification(int p_what) { VisualServer::get_singleton()->instance_set_scenario( instance, RID() ); VisualServer::get_singleton()->instance_set_room(instance,RID()); VisualServer::get_singleton()->instance_attach_skeleton( instance, RID() ); + VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); } break; diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index bbb49a2e783..e9fefe1ba02 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -47,6 +47,7 @@ class VisualInstance : public Spatial { RID _get_visual_instance_rid() const; + protected: diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 88fabb3489d..9a3c7e71ecd 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -927,7 +927,7 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float StringName next=animation_get_next(p_name); - if (next!=StringName()) { + if (next!=StringName() && animation_set.has(next)) { queue(next); } } diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 63a6468a73b..bfa755ff7c6 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -226,6 +226,9 @@ public: void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize); + //void change_scene(const String& p_path); + //Node *get_loaded_scene(); + #ifdef TOOLS_ENABLED void set_edited_scene_root(Node *p_node); Node *get_edited_scene_root() const; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 7e953e44c7f..6b7ed66463c 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -95,8 +95,8 @@ void Viewport::_update_stretch_transform() { if (size_override_stretch && size_override) { - print_line("sive override size "+size_override_size); - print_line("rect size "+rect.size); + //print_line("sive override size "+size_override_size); + //print_line("rect size "+rect.size); stretch_transform=Matrix32(); Size2 scale = rect.size/(size_override_size+size_override_margin*2); stretch_transform.scale(scale); @@ -135,7 +135,9 @@ void Viewport::_update_rect() { } vr.width=rect.size.width; vr.height=rect.size.height; + VisualServer::get_singleton()->viewport_set_rect(viewport,vr); + last_vp_rect=rect; if (canvas_item.is_valid()) { VisualServer::get_singleton()->canvas_item_set_custom_rect(canvas_item,true,rect); @@ -513,6 +515,7 @@ void Viewport::set_rect(const Rect2& p_rect) { if (rect==p_rect) return; rect=p_rect; + _update_rect(); _update_stretch_transform(); @@ -1029,13 +1032,16 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); - Vector2 r = ai.xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 r = ai.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); ev.mouse_motion.x=l.x; ev.mouse_motion.y=l.y; ev.mouse_motion.global_x=g.x; ev.mouse_motion.global_y=g.y; ev.mouse_motion.relative_x=r.x; ev.mouse_motion.relative_y=r.y; + ev.mouse_motion.speed_x=s.x; + ev.mouse_motion.speed_y=s.y; } break; case InputEvent::SCREEN_TOUCH: { @@ -1050,8 +1056,8 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); - Vector2 r = ai.xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); - Vector2 s = ai.xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); + Vector2 r = ai.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); ev.screen_drag.x=t.x; ev.screen_drag.y=t.y; ev.screen_drag.relative_x=r.x; @@ -1185,6 +1191,21 @@ void Viewport::set_physics_object_picking(bool p_enable) { } + +Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { + + Matrix32 xf = get_final_transform(); + return xf.xform(p_viewport_coords); + + +} + +Vector2 Viewport::get_camera_rect_size() const { + + return last_vp_rect.size; +} + + bool Viewport::get_physics_object_picking() { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5d68438f0dc..37f1b357c6e 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -110,6 +110,7 @@ friend class RenderTargetTexture; Size2 size_override_size; Size2 size_override_margin; + Rect2 last_vp_rect; bool transparent_bg; bool render_target_vflip; @@ -229,6 +230,10 @@ public: RenderTargetUpdateMode get_render_target_update_mode() const; Ref get_render_target_texture() const; + + Vector2 get_camera_coords(const Vector2& p_viewport_coords) const; + Vector2 get_camera_rect_size() const; + void queue_screen_capture(); Image get_screen_capture() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index afa127caefc..f3b13f30bf8 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -394,6 +394,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); //scenariofx diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp index 647c8df5d42..226edec9ae2 100644 --- a/scene/resources/baked_light.cpp +++ b/scene/resources/baked_light.cpp @@ -23,6 +23,27 @@ DVector BakedLight::get_octree() const { return VS::get_singleton()->baked_light_get_octree(baked_light); } +void BakedLight::set_light(const DVector& p_light) { + + VS::get_singleton()->baked_light_set_light(baked_light,p_light); +} + +DVector BakedLight::get_light() const { + + return VS::get_singleton()->baked_light_get_light(baked_light); +} + + +void BakedLight::set_sampler_octree(const DVector& p_sampler_octree) { + + VS::get_singleton()->baked_light_set_sampler_octree(baked_light,p_sampler_octree); +} + +DVector BakedLight::get_sampler_octree() const { + + return VS::get_singleton()->baked_light_get_sampler_octree(baked_light); +} + @@ -199,6 +220,43 @@ float BakedLight::get_normal_damp() const { return normal_damp; } +void BakedLight::set_tint(float p_margin) { + tint=p_margin; +} + +float BakedLight::get_tint() const { + + return tint; +} + +void BakedLight::set_saturation(float p_margin) { + saturation=p_margin; +} + +float BakedLight::get_saturation() const { + + return saturation; +} + +void BakedLight::set_ao_radius(float p_ao_radius) { + ao_radius=p_ao_radius; +} + +float BakedLight::get_ao_radius() const { + return ao_radius; +} + +void BakedLight::set_ao_strength(float p_ao_strength) { + + ao_strength=p_ao_strength; +} + +float BakedLight::get_ao_strength() const { + + return ao_strength; +} + + void BakedLight::set_energy_multiplier(float p_multiplier){ energy_multiply=p_multiplier; @@ -329,6 +387,13 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_octree","octree"),&BakedLight::set_octree); ObjectTypeDB::bind_method(_MD("get_octree"),&BakedLight::get_octree); + ObjectTypeDB::bind_method(_MD("set_light","light"),&BakedLight::set_light); + ObjectTypeDB::bind_method(_MD("get_light"),&BakedLight::get_light); + + ObjectTypeDB::bind_method(_MD("set_sampler_octree","sampler_octree"),&BakedLight::set_sampler_octree); + ObjectTypeDB::bind_method(_MD("get_sampler_octree"),&BakedLight::get_sampler_octree); + + ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","gen_size"),&BakedLight::add_lightmap); ObjectTypeDB::bind_method(_MD("erase_lightmap","id"),&BakedLight::erase_lightmap); ObjectTypeDB::bind_method(_MD("clear_lightmaps"),&BakedLight::clear_lightmaps); @@ -357,6 +422,18 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_normal_damp","normal_damp"),&BakedLight::set_normal_damp); ObjectTypeDB::bind_method(_MD("get_normal_damp"),&BakedLight::get_normal_damp); + ObjectTypeDB::bind_method(_MD("set_tint","tint"),&BakedLight::set_tint); + ObjectTypeDB::bind_method(_MD("get_tint"),&BakedLight::get_tint); + + ObjectTypeDB::bind_method(_MD("set_saturation","saturation"),&BakedLight::set_saturation); + ObjectTypeDB::bind_method(_MD("get_saturation"),&BakedLight::get_saturation); + + ObjectTypeDB::bind_method(_MD("set_ao_radius","ao_radius"),&BakedLight::set_ao_radius); + ObjectTypeDB::bind_method(_MD("get_ao_radius"),&BakedLight::get_ao_radius); + + ObjectTypeDB::bind_method(_MD("set_ao_strength","ao_strength"),&BakedLight::set_ao_strength); + ObjectTypeDB::bind_method(_MD("get_ao_strength"),&BakedLight::get_ao_strength); + ObjectTypeDB::bind_method(_MD("set_format","format"),&BakedLight::set_format); ObjectTypeDB::bind_method(_MD("get_format"),&BakedLight::get_format); @@ -384,17 +461,24 @@ void BakedLight::_bind_methods(){ ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/plot_size",PROPERTY_HINT_RANGE,"1.0,16.0,0.01"),_SCS("set_plot_size"),_SCS("get_plot_size")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/energy_mult",PROPERTY_HINT_RANGE,"0.01,4096.0,0.01"),_SCS("set_energy_multiplier"),_SCS("get_energy_multiplier")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/gamma_adjust",PROPERTY_HINT_EXP_EASING),_SCS("set_gamma_adjust"),_SCS("get_gamma_adjust")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/saturation",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("set_saturation"),_SCS("get_saturation")); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/diffuse"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_DIFFUSE); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/specular"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_SPECULAR); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/translucent"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_TRANSLUCENT); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/conserve_energy"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_CONSERVE_ENERGY); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/linear_color"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_LINEAR_COLOR); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"lightmap/use_only_uv2"),_SCS("set_transfer_lightmaps_only_to_uv2"),_SCS("get_transfer_lightmaps_only_to_uv2")); ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_octree"),_SCS("get_octree")); + ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"light",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_light"),_SCS("get_light")); + ADD_PROPERTY( PropertyInfo(Variant::INT_ARRAY,"sampler_octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_sampler_octree"),_SCS("get_sampler_octree")); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"lightmaps",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_lightmap_data"),_SCS("_get_lightmap_data")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/cell_margin",PROPERTY_HINT_RANGE,"0.01,0.8,0.01"),_SCS("set_cell_extra_margin"),_SCS("get_cell_extra_margin")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/edge_damp",PROPERTY_HINT_RANGE,"0.0,8.0,0.1"),_SCS("set_edge_damp"),_SCS("get_edge_damp")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/normal_damp",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_normal_damp"),_SCS("get_normal_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/light_tint",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_tint"),_SCS("get_tint")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_radius",PROPERTY_HINT_RANGE,"0.0,16.0,0.01"),_SCS("set_ao_radius"),_SCS("get_ao_radius")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_strength",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_ao_strength"),_SCS("get_ao_strength")); BIND_CONSTANT( MODE_OCTREE ); BIND_CONSTANT( MODE_LIGHTMAPS ); @@ -415,18 +499,24 @@ BakedLight::BakedLight() { lattice_subdiv=4; plot_size=2.5; bounces=1; - energy_multiply=1.0; - gamma_adjust=1.0; + energy_multiply=2.0; + gamma_adjust=0.7; cell_extra_margin=0.05; edge_damp=0.0; normal_damp=0.0; + saturation=1; + tint=0.0; + ao_radius=2.5; + ao_strength=0.7; format=FORMAT_RGB; transfer_only_uv2=false; + flags[BAKE_DIFFUSE]=true; flags[BAKE_SPECULAR]=false; flags[BAKE_TRANSLUCENT]=true; flags[BAKE_CONSERVE_ENERGY]=false; + flags[BAKE_LINEAR_COLOR]=false; mode=MODE_OCTREE; baked_light=VS::get_singleton()->baked_light_create(); diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h index 57ed7d7aeec..41e1e5f9e0d 100644 --- a/scene/resources/baked_light.h +++ b/scene/resources/baked_light.h @@ -26,6 +26,7 @@ public: BAKE_SPECULAR, BAKE_TRANSLUCENT, BAKE_CONSERVE_ENERGY, + BAKE_LINEAR_COLOR, BAKE_MAX }; @@ -50,6 +51,10 @@ private: float cell_extra_margin; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; + float saturation; int bounces; bool transfer_only_uv2; Format format; @@ -99,6 +104,18 @@ public: void set_normal_damp(float p_margin); float get_normal_damp() const; + void set_tint(float p_margin); + float get_tint() const; + + void set_saturation(float p_saturation); + float get_saturation() const; + + void set_ao_radius(float p_ao_radius); + float get_ao_radius() const; + + void set_ao_strength(float p_ao_strength); + float get_ao_strength() const; + void set_bake_flag(BakeFlags p_flags,bool p_enable); bool get_bake_flag(BakeFlags p_flags) const; @@ -114,6 +131,14 @@ public: void set_octree(const DVector& p_octree); DVector get_octree() const; + void set_light(const DVector& p_light); + DVector get_light() const; + + void set_sampler_octree(const DVector& p_sampler_octree); + DVector get_sampler_octree() const; + + + void add_lightmap(const Ref &p_texture,Size2 p_gen_size=Size2(256,256)); void set_lightmap_gen_size(int p_idx,const Size2& p_size); Size2 get_lightmap_gen_size(int p_idx) const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 351d65654dc..2c278f4feda 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -550,6 +550,10 @@ void ShaderMaterial::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"), &ShaderMaterial::set_shader ); ObjectTypeDB::bind_method(_MD("get_shader:Shader"), &ShaderMaterial::get_shader ); + + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value:var"), &ShaderMaterial::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param:var","param"), &ShaderMaterial::get_shader_param); + ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed ); } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index dc970383b60..55625a2218e 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -503,6 +503,7 @@ public: VS::BakedLightMode mode; RID octree_texture; + RID light_texture; float color_multiplier; //used for both lightmaps and octree Transform octree_transform; Map lightmaps; @@ -514,6 +515,7 @@ public: float lightmap_multiplier; int octree_steps; Vector2 octree_tex_pixel_size; + Vector2 light_tex_pixel_size; }; struct InstanceData { @@ -521,6 +523,7 @@ public: Transform transform; RID skeleton; RID material_override; + RID sampled_light; Vector light_instances; Vector morph_values; BakedLightData *baked_light; @@ -586,6 +589,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0; virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height)=0; + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0; + /*MISC*/ diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp index 637c251cf1c..a671821e25e 100644 --- a/servers/visual/rasterizer_dummy.cpp +++ b/servers/visual/rasterizer_dummy.cpp @@ -1679,6 +1679,18 @@ Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + +RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + /*MISC*/ bool RasterizerDummy::is_texture(const RID& p_rid) const { @@ -1816,6 +1828,14 @@ void RasterizerDummy::free(const RID& p_rid) { Environment *env = environment_owner.get( p_rid ); environment_owner.free(p_rid); memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + }; } diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index 373564249e8..44bca423a43 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/servers/visual/rasterizer_dummy.h @@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer { mutable RID_Owner environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -713,6 +720,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); + /*MISC*/ diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 8250e4c08fa..13ecd49b683 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -1109,8 +1109,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< int tex_w; int tex_h; + int light_tex_w; + int light_tex_h; bool is16; + bool has_light_tex=false; { + DVector::Read r=p_octree.read(); tex_w = decode_uint32(&r[0]); tex_h = decode_uint32(&r[4]); @@ -1123,7 +1127,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< baked_light->data.octree_steps=decode_uint32(&r[16]); baked_light->data.octree_tex_pixel_size.x=1.0/tex_w; baked_light->data.octree_tex_pixel_size.y=1.0/tex_h; + baked_light->data.texture_multiplier=decode_uint32(&r[20]); + light_tex_w=decode_uint16(&r[24]); + light_tex_h=decode_uint16(&r[26]); + print_line("ltexw "+itos(light_tex_w)); + print_line("ltexh "+itos(light_tex_h)); + + if (light_tex_w>0 && light_tex_h>0) { + baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w; + baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h; + has_light_tex=true; + } else { + baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size; + + } + baked_light->octree_aabb.pos.x=decode_float(&r[32]); @@ -1141,12 +1160,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< rasterizer->free(baked_light->data.octree_texture); baked_light->data.octree_texture=RID(); + baked_light->octree_tex_size.x=0; + baked_light->octree_tex_size.y=0; + } + } + + if (baked_light->data.light_texture.is_valid()) { + if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) { + rasterizer->free(baked_light->data.light_texture); + baked_light->data.light_texture=RID(); + baked_light->light_tex_size.x=0; + baked_light->light_tex_size.y=0; } } if (!baked_light->data.octree_texture.is_valid()) { baked_light->data.octree_texture=rasterizer->texture_create(); rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->octree_tex_size.x=tex_w; + baked_light->octree_tex_size.y=tex_h; + } + + if (!baked_light->data.light_texture.is_valid() && has_light_tex) { + baked_light->data.light_texture=rasterizer->texture_create(); + rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->light_tex_size.x=light_tex_w; + baked_light->light_tex_size.y=light_tex_h; + } Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); @@ -1159,6 +1199,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< } + DVector VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ @@ -1174,6 +1215,67 @@ DVector VisualServerRaster::baked_light_get_octree(RID p_baked_light) c } } +void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector p_light) { + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + ERR_FAIL_COND(p_light.size()==0); + + int tex_w=baked_light->light_tex_size.x; + int tex_h=baked_light->light_tex_size.y; + + ERR_FAIL_COND(tex_w==0 && tex_h==0); + ERR_FAIL_COND(!baked_light->data.light_texture.is_valid()); + + + + print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size())); + + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light); + rasterizer->texture_set_data(baked_light->data.light_texture,img); + + + +} + +DVector VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector()); + + if (rasterizer->is_texture(baked_light->data.light_texture)) { + + Image img = rasterizer->texture_get_data(baked_light->data.light_texture); + return img.get_data(); + } else { + return DVector(); + } +} + + + +void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector &p_sampler) { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + + baked_light->sampler=p_sampler; + + + +} + +DVector VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector()); + + return baked_light->sampler; + +} + + void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){ VS_CHANGED; @@ -1192,6 +1294,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){ } +/* BAKED LIGHT SAMPLER */ + +RID VisualServerRaster::baked_light_sampler_create() { + + BakedLightSampler * blsamp = memnew( BakedLightSampler ); + RID rid = baked_light_sampler_owner.make_rid(blsamp); + _update_baked_light_sampler_dp_cache(blsamp); + return rid; +} + +void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){ + + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX); + blsamp->params[p_param]=p_value; + _dependency_queue_update(p_baked_light_sampler,true); +} + +float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{ + + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0); + return blsamp->params[p_param]; +} + +void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) { + + int res = blsamp->resolution; + blsamp->dp_cache.resize(res*res*2); + Vector3 *dp_normals=blsamp->dp_cache.ptr(); + + for(int p=0;p<2;p++) { + float sign = p==0?1:-1; + int ofs = res*res*p; + for(int i=0;i1.0) { + v/=l; + l=1.0; //clamp to avoid imaginary + } + v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function + Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z + n.y*=sign; + dp_normals[j*res+i+ofs]=n; + } + } + } + +} + +void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>64); + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + blsamp->resolution=p_resolution; + _update_baked_light_sampler_dp_cache(blsamp); + +} +int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{ + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + return blsamp->resolution; +} + /* CAMERA API */ RID VisualServerRaster::camera_create() { @@ -1943,6 +2123,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { } + if (instance->baked_light_sampler_info) { + + while (instance->baked_light_sampler_info->owned_instances.size()) { + + instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->baked_light_sampler_info->sampled_light); + } + memdelete( instance->baked_light_sampler_info ); + instance->baked_light_sampler_info=NULL; + } + instance->data.morph_values.clear(); } @@ -1992,6 +2186,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { //instance->portal_info = memnew(Instance::PortalInfo); //instance->portal_info->portal=portal_owner.get(p_base); + } else if (baked_light_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER; + instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->baked_light_sampler_info->sampler=baked_light_sampler_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + } else { ERR_EXPLAIN("Invalid base RID for instance!") ERR_FAIL(); @@ -2607,11 +2811,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{ const Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND_V( !instance,RID() ); if (instance->baked_light) - instance->baked_light->self; + return instance->baked_light->self; return RID(); } + +void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->sampled_light) { + instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); + instance->data.sampled_light=RID(); + } + + if(p_baked_light_sampler.is_valid()) { + Instance *sampler_instance = instance_owner.get( p_baked_light_sampler ); + ERR_FAIL_COND( !sampler_instance ); + ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER ); + instance->sampled_light=sampler_instance; + instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance); + } else { + instance->sampled_light=NULL; + } + + instance->data.sampled_light=RID(); + +} + +RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const { + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,RID() ); + + if (instance->sampled_light) + return instance->sampled_light->self; + else + return RID(); + +} + + void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){ VS_CHANGED; @@ -2747,6 +2990,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { pairable=true; } + if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) { + + pairable_mask=(1<room && (1<base_type)&INSTANCE_GEOMETRY_MASK) { base_type|=INSTANCE_ROOMLESS_MASK; @@ -2859,6 +3109,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) { new_aabb=baked_light->octree_aabb; } break; + case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: { + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid ); + ERR_FAIL_COND(!baked_light_sampler); + float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; + default: {} } @@ -3762,6 +4022,17 @@ void VisualServerRaster::free( RID p_rid ) { baked_light_owner.free(p_rid); memdelete(baked_light); + } else if (baked_light_sampler_owner.owns(p_rid)) { + + _free_attached_instances(p_rid); + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid); + ERR_FAIL_COND(!baked_light_sampler); + //if (baked_light->data.octree_texture.is_valid()) + // rasterizer->free(baked_light->data.octree_texture); + baked_light_sampler_owner.free(p_rid); + memdelete(baked_light_sampler); + } else if (camera_owner.owns(p_rid)) { // delete te camera @@ -3813,7 +4084,9 @@ void VisualServerRaster::free( RID p_rid ) { instance_set_room(p_rid,RID()); instance_set_scenario(p_rid,RID()); instance_geometry_set_baked_light(p_rid,RID()); + instance_geometry_set_baked_light_sampler(p_rid,RID()); instance_set_base(p_rid,RID()); + if (instance->data.skeleton.is_valid()) instance_attach_skeleton(p_rid,RID()); @@ -4957,6 +5230,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance //attempt to conncet portal A (will go through B anyway) //this is a little hackish, but works fine in practice + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL); + B->baked_light_sampler_info->baked_lights.insert(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5006,6 +5288,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance self->_portal_attempt_connect(A); self->_portal_attempt_connect(B); + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER); + B->baked_light_sampler_info->baked_lights.erase(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5197,6 +5488,308 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance } +void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) { + + + BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler; + int res = sampler_opts->resolution; + int dp_size = res*res*2; + Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors + Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals + const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr(); + + + if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) { + if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light); + } + + p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution; + p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2); + + + } + + + zeromem(dp_map,sizeof(Color)*dp_size); + bool valid=false; + int samples=0; + + + for(Set::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) { + + Instance *bl = E->get(); + if (bl->baked_light_info->baked_light->sampler.size()==0) + continue; //not usable + + + Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse(); + for(int i=0;iparams[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION]; + float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH]; + Vector3 s = p_sampled_light->data.transform.basis.get_scale(); + + r*=MAX(MAX(s.x,s.y),s.z); + AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2))); + //ok got octree local AABB + + DVector::Read rp = bl->baked_light_info->baked_light->sampler.read(); + const int *rptr = rp.ptr(); + + int first = rptr[1]; + int depth = rptr[2]; + bool islinear = rptr[3]&1; + depth+=1; + + AABB aabb; + aabb.pos.x=decode_float((const uint8_t*)&rptr[4]); + aabb.pos.y=decode_float((const uint8_t*)&rptr[5]); + aabb.pos.z=decode_float((const uint8_t*)&rptr[6]); + aabb.size.x=decode_float((const uint8_t*)&rptr[7]); + aabb.size.y=decode_float((const uint8_t*)&rptr[8]); + aabb.size.z=decode_float((const uint8_t*)&rptr[9]); + + uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t)); + int *stack_ptr=(int*)alloca(depth*sizeof(int)); + AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB)); + + stack[0]=0; + stack_ptr[0]=first; + aabb_stack[0]=aabb; + Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5; + + + int stack_pos=0; + Color max_col; + + //int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]; + + int lalimit = sample_aabb.get_longest_axis_index(); + float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit]; + + + while(true) { + + + bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0; + + if (aabb_stack[stack_pos].size[lalimit]>16)/256.0); + col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0); + + + max_col.r = MAX(max_col.r,col.r); + max_col.g = MAX(max_col.g,col.g); + max_col.b = MAX(max_col.b,col.b); + + if (!islinear && p_linear_colorspace) { + col=col.to_linear(); + } + + float distance; + + if (aabb_stack[stack_pos].has_point(center)) { + distance=0; + } else { + + Vector3 support = aabb_stack[stack_pos].get_support(norm); + distance = Math::absf(norm.dot(support)-norm.dot(center)); + + } + + if (distance>r) + distance=r; + + float mult = powf(1.0-distance/r,att)*str; + if (mult>0) { + col.r*=mult; + col.g*=mult; + col.b*=mult; + + + + for(int i=0;i>8); + + if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<=depth); + + stack[stack_pos]=0; + stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ]; + aabb_stack[stack_pos]=child_aabb; + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + + } + + //print_line("samples "+itos(samples) ); + + if (valid) { + + for(int i=0;isampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0); + for(Set::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light; + } + + + } else { + + for(Set::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=RID(); //do not use because nothing close + } + } + + + + +/* + highp vec3 vtx = vertex_interp; + vtx.z*=dual_paraboloid.y; //side to affect + vtx.z+=0.01; + dp_clip=vtx.z; + highp float len=length( vtx ); + vtx=normalize(vtx); + vtx.xy/=1.0+vtx.z; + vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near); + vtx+=normalize(vtx)*0.025; + vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace + vertex_interp=vtx; +*/ + + + + +} + + void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { @@ -5248,6 +5841,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 2 - CULL */ int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); light_cull_count=0; + light_samplers_culled=0; /* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); @@ -5408,6 +6002,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S keep=true; } + + } @@ -5420,6 +6016,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S cull_range.min=min; if (max>cull_range.max) cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->baked_light_sampler_info->last_pass!=render_pass) { + if (light_samplers_culledsampled_light; + ins->sampled_light->baked_light_sampler_info->last_pass=render_pass; + } + } } } @@ -5499,7 +6102,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } - { + { //this should eventually change to //assign shadows by distance to camera SortArray sorter; sorter.sort(light_cull_result,light_cull_count); @@ -5520,10 +6123,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } } + /* ENVIRONMENT */ - - /* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/ - RID environment; if (p_camera->env.is_valid()) //camera has more environment priority environment=p_camera->env; @@ -5532,6 +6133,22 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S else environment=p_scenario->fallback_environment; + + /* STEP 6 - SAMPLE BAKED LIGHT */ + + bool islinear =false; + if (environment.is_valid()) { + islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB); + } + + for(int i=0;itransform,light_sampler_cull_result[i],islinear); + } + + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); rasterizer->set_viewport(viewport_rect); @@ -5838,6 +6455,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ desired_rect.x+=p_ofs_x; desired_rect.y+=p_ofs_y; + // if the viewport is different than the actual one, change it if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x || @@ -5847,7 +6465,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ viewport_rect=desired_rect; - rasterizer->set_viewport(viewport_rect); + rasterizer->set_viewport(viewport_rect); } @@ -5995,7 +6613,14 @@ void VisualServerRaster::_draw_viewports() { int window_w = OS::get_singleton()->get_video_mode(E->get()).width; int window_h = OS::get_singleton()->get_video_mode(E->get()).height; - _draw_viewport(vp,0,0,window_w,window_h); + Rect2 r(0,0,vp->rect.width,vp->rect.height); + if (r.size.width==0) + r.size.width=window_w; + if (r.size.height==0) + r.size.height=window_w; + + + _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height); } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 8ed348affaf..3064f9ceb08 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer { MAX_LIGHTS_CULLED=256, MAX_ROOM_CULL=32, MAX_EXTERIOR_PORTALS=128, + MAX_LIGHT_SAMPLERS=256, INSTANCE_ROOMLESS_MASK=(1<<20) @@ -90,12 +91,29 @@ class VisualServerRaster : public VisualServer { struct BakedLight { Rasterizer::BakedLightData data; + DVector sampler; AABB octree_aabb; Size2i octree_tex_size; + Size2i light_tex_size; }; + struct BakedLightSampler { + float params[BAKED_LIGHT_SAMPLER_MAX]; + int resolution; + Vector dp_cache; + + BakedLightSampler() { + params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0; + params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0; + params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0; + params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1; + resolution=16; + } + }; + + void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp); struct Camera { enum Type { @@ -169,6 +187,7 @@ class VisualServerRaster : public VisualServer { List::Element *RE; Instance *baked_light; List::Element *BLE; + Instance *sampled_light; bool exterior; uint64_t last_render_pass; @@ -179,6 +198,8 @@ class VisualServerRaster : public VisualServer { InstanceSet lights; bool light_cache_dirty; + + struct RoomInfo { Transform affine_inverse; @@ -235,6 +256,23 @@ class VisualServerRaster : public VisualServer { Transform affine_inverse; List owned_instances; }; + + struct BakedLightSamplerInfo { + + Set baked_lights; + Set owned_instances; + BakedLightSampler *sampler; + int resolution; + Vector light_bufer; + RID sampled_light; + uint64_t last_pass; + Transform xform; // viewspace normal to lightspace, might not use one. + BakedLightSamplerInfo() { + sampler=NULL; + last_pass=0; + resolution=0; + } + }; struct ParticlesInfo { @@ -247,6 +285,7 @@ class VisualServerRaster : public VisualServer { ParticlesInfo *particles_info; PortalInfo * portal_info; BakedLightInfo * baked_light_info; + BakedLightSamplerInfo * baked_light_sampler_info; Instance() { @@ -282,6 +321,8 @@ class VisualServerRaster : public VisualServer { baked_light=NULL; baked_light_info=NULL; + baked_light_sampler_info=NULL; + sampled_light=NULL; BLE=NULL; light_cache_dirty=true; @@ -603,6 +644,9 @@ class VisualServerRaster : public VisualServer { int exterior_portal_cull_count; bool exterior_visited; + Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS]; + int light_samplers_culled; + Instance *room_cull_result[MAX_ROOM_CULL]; int room_cull_count; bool room_cull_enabled; @@ -638,6 +682,7 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner portal_owner; mutable RID_Owner baked_light_owner; + mutable RID_Owner baked_light_sampler_owner; mutable RID_Owner camera_owner; mutable RID_Owner viewport_owner; @@ -658,6 +703,8 @@ class VisualServerRaster : public VisualServer { bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to); void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal); void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL); + void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace); + void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity); void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); @@ -953,12 +1000,28 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector p_octree); virtual DVector baked_light_get_octree(RID p_baked_light) const; + virtual void baked_light_set_light(RID p_baked_light,const DVector p_light); + virtual DVector baked_light_get_light(RID p_baked_light) const; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector &p_sampler); + virtual DVector baked_light_get_sampler_octree(RID p_baked_light) const; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier); virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id); virtual void baked_light_clear_lightmaps(RID p_baked_light); + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create(); + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value); + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution); + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const; + /* CAMERA API */ virtual RID camera_create(); @@ -1096,6 +1159,9 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light); virtual RID instance_geometry_get_baked_light(RID p_instance) const; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler); + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id); virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 1ad8c859865..a4653b10131 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -909,6 +909,12 @@ public: FUNC2(baked_light_set_octree,RID,DVector); FUNC1RC(DVector,baked_light_get_octree,RID); + FUNC2(baked_light_set_light,RID,DVector); + FUNC1RC(DVector,baked_light_get_light,RID); + + FUNC2(baked_light_set_sampler_octree,RID,const DVector&); + FUNC1RC(DVector,baked_light_get_sampler_octree,RID); + FUNC2(baked_light_set_lightmap_multiplier,RID,float); FUNC1RC(float,baked_light_get_lightmap_multiplier,RID); @@ -916,6 +922,14 @@ public: FUNC1(baked_light_clear_lightmaps,RID); + FUNC0R(RID,baked_light_sampler_create); + + FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float ); + FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam ); + + FUNC2(baked_light_sampler_set_resolution,RID,int); + FUNC1RC(int,baked_light_sampler_get_resolution,RID); + /* CAMERA API */ FUNC0R(RID,camera_create); @@ -1055,6 +1069,9 @@ public: FUNC2(instance_geometry_set_baked_light,RID, RID ); FUNC1RC(RID,instance_geometry_get_baked_light,RID); + FUNC2(instance_geometry_set_baked_light_sampler,RID, RID ); + FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID); + FUNC2(instance_geometry_set_baked_light_texture_index,RID, int); FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID); diff --git a/servers/visual_server.h b/servers/visual_server.h index 366758f1d85..ed04b0d09ca 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -590,12 +590,35 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector p_octree)=0; virtual DVector baked_light_get_octree(RID p_baked_light) const=0; + virtual void baked_light_set_light(RID p_baked_light,const DVector p_light)=0; + virtual DVector baked_light_get_light(RID p_baked_light) const=0; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector &p_sampler)=0; + virtual DVector baked_light_get_sampler_octree(RID p_baked_light) const=0; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0; virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0; virtual void baked_light_clear_lightmaps(RID p_baked_light)=0; + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create()=0; + + enum BakedLightSamplerParam { + BAKED_LIGHT_SAMPLER_RADIUS, + BAKED_LIGHT_SAMPLER_STRENGTH, + BAKED_LIGHT_SAMPLER_ATTENUATION, + BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + BAKED_LIGHT_SAMPLER_MAX + }; + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0; + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0; + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0; /* CAMERA API */ @@ -824,7 +847,8 @@ public: INSTANCE_ROOM, INSTANCE_PORTAL, INSTANCE_BAKED_LIGHT, - + INSTANCE_BAKED_LIGHT_SAMPLER, + INSTANCE_GEOMETRY_MASK=(1< #include "io/marshalls.h" #include "tools/editor/editor_node.h" +#include "tools/editor/editor_settings.h" +void baked_light_baker_add_64f(double *dst,double value); +void baked_light_baker_add_64i(int64_t *dst,int64_t value); + +//-separar en 2 testuras? +//*mejorar performance y threads +//*modos lineales +//*saturacion + _FORCE_INLINE_ static uint64_t get_uv_normal_bit(const Vector3& p_vector) { int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*6.0/Math_PI+0.5)); @@ -66,6 +75,12 @@ BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref& image.convert(Image::FORMAT_RGBA); } + if (imgtex->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR) { + Image copy = image; + copy.srgb_to_linear(); + image=copy; + } + DVector dvt=image.get_data(); DVector::Read r=dvt.read(); MeshTexture mt; @@ -105,8 +120,13 @@ void BakedLightBaker::_add_mesh(const Ref& p_mesh,const Ref& p_m if (fm.is_valid()) { //fixed route mm.diffuse.color=fm->get_parameter(FixedMaterial::PARAM_DIFFUSE); + if (linear_color) + mm.diffuse.color=mm.diffuse.color.to_linear(); mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_DIFFUSE)); mm.specular.color=fm->get_parameter(FixedMaterial::PARAM_SPECULAR); + if (linear_color) + mm.specular.color=mm.specular.color.to_linear(); + mm.specular.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_SPECULAR)); } else { @@ -270,6 +290,11 @@ void BakedLightBaker::_parse_geometry(Node* p_node) { dirl.type=VS::LightType(dl->get_light_type()); dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + if (linear_color) + dirl.diffuse=dirl.diffuse.to_linear(); + if (linear_color) + dirl.specular=dirl.specular.to_linear(); + dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); dirl.pos=dl->get_global_transform().origin; dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); @@ -472,8 +497,11 @@ void BakedLightBaker::_make_bvh() { } bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); + ray_stack = memnew_arr(uint32_t,max_depth); bvh_stack = memnew_arr(BVH*,max_depth); + + bvh_depth = max_depth; } void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_depth) { @@ -563,6 +591,12 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de child->aabb.pos.z+=child->aabb.size.z; + child->full_accum[0]=0; + child->full_accum[1]=0; + child->full_accum[2]=0; + child->sampler_ofs=0; + + if (stack_pos==octree_depth-1) { child->leaf=true; @@ -585,14 +619,10 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de cell_count++; int lz = lights.size(); - child->light = memnew_arr(OctantLight,lz); - - for(int li=0;lilight[li].accum[ci][0]=0; - child->light[li].accum[ci][1]=0; - child->light[li].accum[ci][2]=0; - } + for(int ci=0;ci<8;ci++) { + child->light_accum[ci][0]=0; + child->light_accum[ci][1]=0; + child->light_accum[ci][2]=0; } child->parent=ptr_stack[stack_pos]; @@ -797,12 +827,12 @@ void BakedLightBaker::_make_octree() { -void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light, const Plane& p_plane) { +void BakedLightBaker::_plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light,const Color& p_tint_light,bool p_only_full, const Plane& p_plane) { //stackless version - uint32_t *stack=octant_stack; - uint32_t *ptr_stack=octantptr_stack; + uint32_t *stack=thread_stack.octant_stack; + uint32_t *ptr_stack=thread_stack.octantptr_stack; Octant *octants=octant_pool.ptr(); stack[0]=0; @@ -815,6 +845,29 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, Octant &octant=octants[ptr_stack[stack_pos]]; + if (stack[stack_pos]==0) { + + + Vector3 pos = octant.aabb.pos + octant.aabb.size*0.5; + float md = 1<<(octree_depth - stack_pos ); + float r=cell_size*plot_size*md; + float div = 1.0/(md*md*md); + //div=1.0; + + + float d = p_plot_pos.distance_to(pos); + + if ((p_plane.distance_to(pos)>-cell_size*1.75*md) && d<=r) { + + + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + + baked_light_baker_add_64f(&octant.full_accum[0],p_tint_light.r*intensity*div); + baked_light_baker_add_64f(&octant.full_accum[1],p_tint_light.g*intensity*div); + baked_light_baker_add_64f(&octant.full_accum[2],p_tint_light.b*intensity*div); + } + } + if (octant.leaf) { @@ -822,41 +875,44 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, //if (p_plane.normal.dot(octant.aabb.get_support(p_plane.normal)) < p_plane.d-CMP_EPSILON) { //octants behind are no go - - float r=cell_size*plot_size; - for(int i=0;i<8;i++) { - Vector3 pos=octant.aabb.pos; - if (i&1) - pos.x+=octant.aabb.size.x; - if (i&2) - pos.y+=octant.aabb.size.y; - if (i&4) - pos.z+=octant.aabb.size.z; + if (!p_only_full) { + float r=cell_size*plot_size; + for(int i=0;i<8;i++) { + Vector3 pos=octant.aabb.pos; + if (i&1) + pos.x+=octant.aabb.size.x; + if (i&2) + pos.y+=octant.aabb.size.y; + if (i&4) + pos.z+=octant.aabb.size.z; - float d = p_plot_pos.distance_to(pos); + float d = p_plot_pos.distance_to(pos); - if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) { + if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) { - float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. - if (edge_damp>0) { - Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]); - if (normal.x>0 || normal.y>0 || normal.z>0) { + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + if (edge_damp>0) { + Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]); + if (normal.x>0 || normal.y>0 || normal.z>0) { - float damp = Math::abs(p_plane.normal.dot(normal)); - intensity*=pow(damp,edge_damp); + float damp = Math::abs(p_plane.normal.dot(normal)); + intensity*=pow(damp,edge_damp); + } } + + //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); + //intensity = Math::cos(d*Math_PI*0.5/r); + + baked_light_baker_add_64f(&octant.light_accum[i][0],p_light.r*intensity); + baked_light_baker_add_64f(&octant.light_accum[i][1],p_light.g*intensity); + baked_light_baker_add_64f(&octant.light_accum[i][2],p_light.b*intensity); + + } - - //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); - //intensity = Math::cos(d*Math_PI*0.5/r); - - octant.light[p_light_index].accum[i][0]+=p_light.r*intensity; - octant.light[p_light_index].accum[i][1]+=p_light.g*intensity; - octant.light[p_light_index].accum[i][2]+=p_light.b*intensity; } } @@ -893,11 +949,11 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, } -float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) { +float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) { - uint32_t* stack = ray_stack; - BVH **bstack = bvh_stack; + uint32_t* stack = thread_stack.ray_stack; + BVH **bstack = thread_stack.bvh_stack; enum { TEST_AABB_BIT=0, @@ -915,6 +971,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons n/=len; + real_t d=1e10; bool inters=false; Vector3 r_normal; @@ -1139,7 +1196,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons #endif - ret=_throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + ret=_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) { @@ -1150,7 +1207,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons Vector3 rn = n - r_normal *r_normal.dot(n) * 2.0; - _throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } } @@ -1158,19 +1215,25 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons // _plot_light_point(r_point,octree,octree_aabb,p_light); - Color plot_light=diffuse_at_point; + Color plot_light=res_light.linear_interpolate(diffuse_at_point,tint); plot_light.r*=att; plot_light.g*=att; plot_light.b*=att; + Color tint_light=diffuse_at_point; + tint_light.r*=att; + tint_light.g*=att; + tint_light.b*=att; - if (!p_first_bounce) { + bool skip=false; + + if (!p_first_bounce || p_bake_direct) { float r = plot_size * cell_size*2; if (dist0 && dtexture_x=0; + oct->texture_y=0; + oct_idx=oct->next_leaf; + + } + + oct_idx=leaf_list; + //assign + while(oct_idx) { + + BakedLightBaker::Octant *oct = &octants[oct_idx]; + if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { + //was not processed + uint32_t current_idx=oct_idx; + int reused=0; + + while(current_idx) { + BakedLightBaker::Octant *o = &octants[current_idx]; + if (col+1 >= otex_w) { + col=0; + row+=4; + } + o->texture_x=col; + o->texture_y=row; + processed++; + + if (o->bake_neighbour) { + reused++; + } + col+=o->bake_neighbour ? 1 : 2; //reuse neighbour + current_idx=o->bake_neighbour; + } + + if (reused>longest_line_reused) { + longest_line_reused=reused; + } + } + oct_idx=oct->next_leaf; + } + + row+=4; + + if (otex_w < row) { + + otex_w*=2; + } else { + + baked_light_texture_w=otex_w; + baked_light_texture_h=nearest_power_of_2(row); + print_line("w: "+itos(otex_w)); + print_line("h: "+itos(row)); + break; + } + + + } + + { - int otex_w=(1<texture_x=0; - oct->texture_y=0; - oct_idx=oct->next_leaf; - - } - - oct_idx=leaf_list; - - - print_line("begin at row "+itos(row)); - int longest_line_reused=0; int col=0; - int processed=0; - - while(oct_idx) { - - BakedLightBaker::Octant *oct = &octants[oct_idx]; - if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { - //was not processed - uint32_t current_idx=oct_idx; - int reused=0; - - while(current_idx) { - BakedLightBaker::Octant *o = &octants[current_idx]; - if (col+1 >= otex_w) { - col=0; - row+=4; - } - o->texture_x=col; - o->texture_y=row; - processed++; - - if (o->bake_neighbour) { - reused++; - } - col+=o->bake_neighbour ? 1 : 2; //reuse neighbour - current_idx=o->bake_neighbour; - } - - if (reused>longest_line_reused) { - longest_line_reused=reused; - } - } - oct_idx=oct->next_leaf; - } - - print_line("processed "+itos(processed)); - - print_line("longest reused: "+itos(longest_line_reused)); col=0; row+=4; @@ -1478,7 +1560,25 @@ double BakedLightBaker::get_normalization(int p_light_idx) const { return nrg; } -void BakedLightBaker::throw_rays(int p_amount) { + + +double BakedLightBaker::get_modifier(int p_light_idx) const { + + double nrg=0; + + const LightData &dl=lights[p_light_idx]; + double cell_area = cell_size*cell_size;; + //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area); + nrg=cell_area; + nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel + nrg*=dl.constant; + //nrg*=5; + + + return nrg; +} + +void BakedLightBaker::throw_rays(ThreadStack& thread_stack,int p_amount) { @@ -1488,6 +1588,8 @@ void BakedLightBaker::throw_rays(int p_amount) { int amount = p_amount * total_light_area / dl.area; + double mod = 1.0/double(get_modifier(i)); + mod*=p_amount/float(amount); switch(dl.type) { @@ -1502,12 +1604,15 @@ void BakedLightBaker::throw_rays(int p_amount) { from+=dl.left*(r2*2.0-1.0); Vector3 to = from+dl.dir*dl.length; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; + dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.length,col,NULL,0,0,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.length,col,NULL,0,0,max_bounces,true); } } break; case VS::LIGHT_OMNI: { @@ -1543,13 +1648,14 @@ void BakedLightBaker::throw_rays(int p_amount) { #endif Vector3 to = dl.pos+dir*dl.radius; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); } @@ -1574,13 +1680,14 @@ void BakedLightBaker::throw_rays(int p_amount) { Vector3 to = dl.pos+dir*dl.radius; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); } @@ -1622,6 +1729,10 @@ void BakedLightBaker::bake(const Ref &p_light, Node* p_node) { edge_damp=baked_light->get_edge_damp(); normal_damp=baked_light->get_normal_damp(); octree_extra_margin=baked_light->get_cell_extra_margin(); + tint=baked_light->get_tint(); + ao_radius=baked_light->get_ao_radius(); + ao_strength=baked_light->get_ao_strength(); + linear_color=baked_light->get_bake_flag(BakedLight::BAKE_LINEAR_COLOR); baked_textures.clear(); for(int i=0;iget_lightmaps_count();i++) { @@ -1651,13 +1762,134 @@ void BakedLightBaker::bake(const Ref &p_light, Node* p_node) { } -void BakedLightBaker::update_octree_image(DVector &p_image) { +void BakedLightBaker::update_octree_sampler(DVector &p_sampler) { + + BakedLightBaker::Octant *octants=octant_pool.ptr(); + double norm = 1.0/double(total_rays); + + + + if (p_sampler.size()==0 || first_bake_to_map) { + + Vector tmp_smp; + tmp_smp.resize(32); //32 for header + + for(int i=0;i<32;i++) { + tmp_smp[i]=0; + } + + for(int i=octant_pool_size-1;i>=0;i--) { + + if (i==0) + tmp_smp[1]=tmp_smp.size(); + + Octant &octant=octants[i]; + octant.sampler_ofs = tmp_smp.size(); + int idxcol[2]={0,0}; + + int r = CLAMP((octant.full_accum[0]*norm)*2048,0,32767); + int g = CLAMP((octant.full_accum[1]*norm)*2048,0,32767); + int b = CLAMP((octant.full_accum[2]*norm)*2048,0,32767); + + idxcol[0]|=r; + idxcol[1]|=(g<<16)|b; + + if (octant.leaf) { + tmp_smp.push_back(idxcol[0]); + tmp_smp.push_back(idxcol[1]); + } else { + + for(int j=0;j<8;j++) { + if (octant.children[j]) { + idxcol[0]|=(1<<(j+16)); + } + } + tmp_smp.push_back(idxcol[0]); + tmp_smp.push_back(idxcol[1]); + for(int j=0;j<8;j++) { + if (octant.children[j]) { + tmp_smp.push_back(octants[octant.children[j]].sampler_ofs); + if (octants[octant.children[j]].sampler_ofs==0) { + print_line("FUUUUUUUUCK"); + } + } + } + } + + } + + p_sampler.resize(tmp_smp.size()); + DVector::Write w = p_sampler.write(); + int ss = tmp_smp.size(); + for(int i=0;iget_gamma_adjust(); + double mult = baked_light->get_energy_multiplier(); + float saturation = baked_light->get_saturation(); + + DVector::Write w = p_sampler.write(); + + encode_uint32(octree_depth,(uint8_t*)&w[2]); + encode_uint32(linear_color,(uint8_t*)&w[3]); + + encode_float(octree_aabb.pos.x,(uint8_t*)&w[4]); + encode_float(octree_aabb.pos.y,(uint8_t*)&w[5]); + encode_float(octree_aabb.pos.z,(uint8_t*)&w[6]); + encode_float(octree_aabb.size.x,(uint8_t*)&w[7]); + encode_float(octree_aabb.size.y,(uint8_t*)&w[8]); + encode_float(octree_aabb.size.z,(uint8_t*)&w[9]); + + //norm*=multiplier; + + for(int i=octant_pool_size-1;i>=0;i--) { + + Octant &octant=octants[i]; + int idxcol[2]={w[octant.sampler_ofs],w[octant.sampler_ofs+1]}; + + double rf=pow(octant.full_accum[0]*norm*mult,gamma); + double gf=pow(octant.full_accum[1]*norm*mult,gamma); + double bf=pow(octant.full_accum[2]*norm*mult,gamma); + + double gray = (rf+gf+bf)/3.0; + rf = gray + (rf-gray)*saturation; + gf = gray + (gf-gray)*saturation; + bf = gray + (bf-gray)*saturation; + + + int r = CLAMP((rf)*2048,0,32767); + int g = CLAMP((gf)*2048,0,32767); + int b = CLAMP((bf)*2048,0,32767); + + idxcol[0]=((idxcol[0]>>16)<<16)|r; + idxcol[1]=(g<<16)|b; + w[octant.sampler_ofs]=idxcol[0]; + w[octant.sampler_ofs+1]=idxcol[1]; + } + +} + +void BakedLightBaker::update_octree_images(DVector &p_octree,DVector &p_light) { int len = baked_octree_texture_w*baked_octree_texture_h*4; - p_image.resize(len); - DVector::Write w = p_image.write(); + p_octree.resize(len); + + int ilen = baked_light_texture_w*baked_light_texture_h*4; + p_light.resize(ilen); + + + DVector::Write w = p_octree.write(); zeromem(w.ptr(),len); + + DVector::Write iw = p_light.write(); + zeromem(iw.ptr(),ilen); + float gamma = baked_light->get_gamma_adjust(); float mult = baked_light->get_energy_multiplier(); @@ -1668,6 +1900,13 @@ void BakedLightBaker::update_octree_image(DVector &p_image) { w[i+3]=0xFF; } + for(int i=0;iget_format()==BakedLight::FORMAT_HDR8) @@ -1678,6 +1917,9 @@ void BakedLightBaker::update_octree_image(DVector &p_image) { encode_float(1< &p_image) { BakedLightBaker::Octant *octants=octant_pool.ptr(); int octant_count=octant_pool_size; uint8_t *ptr = w.ptr(); + uint8_t *lptr = iw.ptr(); int child_offsets[8]={ @@ -1703,7 +1946,18 @@ void BakedLightBaker::update_octree_image(DVector &p_image) { baked_octree_texture_w*8+baked_octree_texture_w*4+4, }; - Vector norm_arr; + int lchild_offsets[8]={ + 0, + 4, + baked_light_texture_w*4, + baked_light_texture_w*4+4, + baked_light_texture_w*8+0, + baked_light_texture_w*8+4, + baked_light_texture_w*8+baked_light_texture_w*4, + baked_light_texture_w*8+baked_light_texture_w*4+4, + }; + + /*Vector norm_arr; norm_arr.resize(lights.size()); for(int i=0;i &p_image) { } const double *normptr=norm_arr.ptr(); - +*/ + double norm = 1.0/double(total_rays); int lz=lights.size(); mult/=multiplier; + double saturation = baked_light->get_saturation(); for(int i=0;iilen); //write colors for(int j=0;j<8;j++) { //if (!oct.children[j]) // continue; - uint8_t *iptr=&ptr[ofs+child_offsets[j]]; - float r=0; - float g=0; - float b=0; + uint8_t *iptr=&lptr[ofs+lchild_offsets[j]]; - for(int k=0;k &p_image) { } else { + int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2; + ERR_CONTINUE(ofs<0 || ofs >len); //write indices for(int j=0;j<8;j++) { @@ -1822,49 +2082,61 @@ void BakedLightBaker::_bake_thread_func(void *arg) { BakedLightBaker *ble = (BakedLightBaker*)arg; - ble->rays_at_snap_time=ble->total_rays; - ble->snap_time=OS::get_singleton()->get_ticks_usec(); + + + ThreadStack thread_stack; + + thread_stack.ray_stack = memnew_arr(uint32_t,ble->bvh_depth); + thread_stack.bvh_stack = memnew_arr(BVH*,ble->bvh_depth); + thread_stack.octant_stack = memnew_arr(uint32_t,ble->octree_depth*2 ); + thread_stack.octantptr_stack = memnew_arr(uint32_t,ble->octree_depth*2 ); while(!ble->bake_thread_exit) { - ble->throw_rays(1000); - uint64_t t=OS::get_singleton()->get_ticks_usec(); - if (t-ble->snap_time>1000000) { - - double time = (t-ble->snap_time)/1000000.0; - - int rays=ble->total_rays-ble->rays_at_snap_time; - ble->rays_sec=int(rays/time); - ble->snap_time=OS::get_singleton()->get_ticks_usec(); - ble->rays_at_snap_time=ble->total_rays; - } + ble->throw_rays(thread_stack,1000); } + memdelete_arr(thread_stack.ray_stack ); + memdelete_arr(thread_stack.bvh_stack ); + memdelete_arr(thread_stack.octant_stack ); + memdelete_arr(thread_stack.octantptr_stack ); + } void BakedLightBaker::_start_thread() { - if (thread!=NULL) + if (threads.size()!=0) return; bake_thread_exit=false; - thread=Thread::create(_bake_thread_func,this); + int thread_count = EDITOR_DEF("light_baker/custom_bake_threads",0); + if (thread_count<=0 || thread_count>64) + thread_count=OS::get_singleton()->get_processor_count(); + + //thread_count=1; + threads.resize(thread_count); + for(int i=0;i norm_arr; - norm_arr.resize(lights.size()); + //if (octant_pool[i].leaf) { + // memdelete_arr( octant_pool[i].light ); + //} Vector norm_arr; + //norm_arr.resize(lights.size()); for(int i=0;i(); total_rays=0; @@ -2414,12 +2687,11 @@ BakedLightBaker::BakedLightBaker() { baked_octree_texture_h=0; paused=false; baking=false; - thread=NULL; + bake_thread_exit=false; - rays_at_snap_time=0; - snap_time=0; - rays_sec=0; total_rays=0; + first_bake_to_map=true; + linear_color=false; } diff --git a/tools/editor/plugins/baked_light_baker.h b/tools/editor/plugins/baked_light_baker.h index e0a9d91cd42..8fbeeddc6a6 100644 --- a/tools/editor/plugins/baked_light_baker.h +++ b/tools/editor/plugins/baked_light_baker.h @@ -15,17 +15,19 @@ public: OCTANT_POOL_CHUNK=1000000 }; - struct OctantLight { + //struct OctantLight { - double accum[8][3]; - }; + // double accum[8][3]; + //}; struct Octant { bool leaf; AABB aabb; uint16_t texture_x; uint16_t texture_y; + int sampler_ofs; float normal_accum[8][3]; + double full_accum[3]; int parent; union { struct { @@ -33,7 +35,7 @@ public: float offset[3]; int bake_neighbour; bool first_neighbour; - OctantLight *light; + double light_accum[8][3]; }; int children[8]; }; @@ -234,32 +236,49 @@ public: Transform base_inv; int leaf_list; int octree_depth; + int bvh_depth; int cell_count; uint32_t *ray_stack; + BVH **bvh_stack; uint32_t *octant_stack; uint32_t *octantptr_stack; + + struct ThreadStack { + uint32_t *octant_stack; + uint32_t *octantptr_stack; + uint32_t *ray_stack; + BVH **bvh_stack; + }; + Map endpoint_normal; Map endpoint_normal_bits; - BVH **bvh_stack; + float cell_size; float plot_size; //multiplied by cell size float octree_extra_margin; int max_bounces; - uint64_t total_rays; + int64_t total_rays; bool use_diffuse; bool use_specular; bool use_translucency; + bool linear_color; int baked_octree_texture_w; int baked_octree_texture_h; + int baked_light_texture_w; + int baked_light_texture_h; int lattice_size; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; bool paused; bool baking; + bool first_bake_to_map; Map,MeshMaterial*> mat_map; Map,MeshTexture*> tex_map; @@ -285,19 +304,16 @@ public: //void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,int p_octant=0); - void _plot_light(int p_light_index,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Plane& p_plane); + void _plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Color& p_tint_light,bool p_only_full,const Plane& p_plane); //void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light); - float _throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); + float _throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); float total_light_area; - uint64_t rays_at_snap_time; - uint64_t snap_time; - int rays_sec; + Vector threads; - Thread *thread; bool bake_thread_exit; static void _bake_thread_func(void *arg); @@ -306,18 +322,20 @@ public: public: - void throw_rays(int p_amount); + void throw_rays(ThreadStack &thread_stack, int p_amount); double get_normalization(int p_light_idx) const; + double get_modifier(int p_light_idx) const; void bake(const Ref& p_light,Node *p_base); bool is_baking(); void set_pause(bool p_pause); bool is_paused(); - int get_rays_sec() { return rays_sec; } + uint64_t get_rays_thrown() { return total_rays; } Error transfer_to_lightmaps(); - void update_octree_image(DVector &p_image); + void update_octree_sampler(DVector &p_sampler); + void update_octree_images(DVector &p_octree,DVector &p_light); Ref get_baked_light() { return baked_light; } diff --git a/tools/editor/plugins/baked_light_baker_cmpxchg.cpp b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp new file mode 100644 index 00000000000..d08c9f64846 --- /dev/null +++ b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp @@ -0,0 +1,84 @@ + +#include "typedefs.h" + + +#ifdef WINDOWS_ENABLED + +#include "windows.h" + +void baked_light_baker_add_64f(double *dst,double value) { + + union { + int64_t i; + double f; + } swapy; + + + while(true) { + swapy.f=*dst; + int64_t from = swapy.i; + swapy.f+=value; + int64_t to=swapy.i; + int64_t result = InterlockedCompareExchange64((int64_t*)dst,to,from); + if (result==from) + break; + } + +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + while(true) { + int64_t from = *dst; + int64_t to = from+value; + int64_t result = InterlockedCompareExchange64(dst,to,from); + if (result==from) + break; + } +} + +#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 + +void baked_light_baker_add_64f(double *dst,double value) { + + + union { + int64_t i; + double f; + } swapy; + + + while(true) { + swapy.f=*dst; + int64_t from = swapy.i; + swapy.f+=value; + int64_t to=swapy.i; + if (__sync_bool_compare_and_swap((int64_t*)dst,from,to)) + break; + } +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + while(!__sync_bool_compare_and_swap(dst,*dst,(*dst)+value)) {} + +} + +#else + +//in goder (the god of programmers) we trust +#warning seems this platform or compiler does not support safe cmpxchg, your baked lighting may be funny + +void baked_light_baker_add_64f(double *dst,double value) { + + *dst+=value; + +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + *dst+=value; + +} + +#endif diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp index 3d48f2e7322..2f8393f1027 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.cpp +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -111,7 +111,10 @@ void BakedLightEditor::_notification(int p_option) { #endif ERR_FAIL_COND(node->get_baked_light().is_null()); - baker->update_octree_image(octree_texture); + baker->update_octree_images(octree_texture,light_texture); + baker->update_octree_sampler(octree_sampler); + // print_line("sampler size: "+itos(octree_sampler.size()*4)); + #if 1 //debug Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,octree_texture); @@ -121,11 +124,19 @@ void BakedLightEditor::_notification(int p_option) { #endif - bake_info->set_text("rays/s: "+itos(baker->get_rays_sec())); + + + uint64_t rays_snap = baker->get_rays_thrown(); + int rays_sec = (rays_snap-last_rays_time)*1.0-(update_timeout); + last_rays_time=rays_snap; + + bake_info->set_text("rays/s: "+itos(rays_sec)); update_timeout=1; print_line("MSUPDATE: "+itos(OS::get_singleton()->get_ticks_msec()-t)); t=OS::get_singleton()->get_ticks_msec(); node->get_baked_light()->set_octree(octree_texture); + node->get_baked_light()->set_light(light_texture); + node->get_baked_light()->set_sampler_octree(octree_sampler); node->get_baked_light()->set_edited(true); print_line("MSSET: "+itos(OS::get_singleton()->get_ticks_msec()-t)); @@ -195,6 +206,9 @@ void BakedLightEditor::_bake_pressed() { baker->bake(node->get_baked_light(),node); node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE); update_timeout=0; + + last_rays_time=0; + set_process(true); } diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h index 7912bd92e51..27ab88d70b3 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.h +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -23,6 +23,8 @@ class BakedLightEditor : public Control { float update_timeout; DVector octree_texture; + DVector light_texture; + DVector octree_sampler; BakedLightBaker *baker; AcceptDialog *err_dialog; @@ -33,6 +35,9 @@ class BakedLightEditor : public Control { Button *button_make_lightmaps; Label *bake_info; + uint64_t last_rays_time; + + BakedLightInstance *node; diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 074fa5c946f..e91e7a94fea 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -1971,7 +1971,7 @@ void SpatialEditorViewport::_preview_exited_scene() { void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { - uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx)|(1<instance_create(); diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py index 7899098e3d2..a92b97b8a98 100644 --- a/tools/export/blender25/io_scene_dae/export_dae.py +++ b/tools/export/blender25/io_scene_dae/export_dae.py @@ -485,9 +485,17 @@ class DaeExporter: uv_layer_count=len(mesh.uv_textures) if (len(mesh.uv_textures)): - mesh.calc_tangents() + try: + mesh.calc_tangents() + except: + print("Warning, blender API is fucked up, not exporting UVs for this object.") + uv_layer_count=0 + mesh.calc_normals_split() + has_tangents=False + else: mesh.calc_normals_split() + has_tangents=False for fi in range(len(mesh.polygons)):