-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
This commit is contained in:
Juan Linietsky 2014-10-27 22:54:32 -03:00
parent 9608d4255e
commit e82dc40205
61 changed files with 2163 additions and 354 deletions

View file

@ -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')

View file

@ -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;

View file

@ -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;

View file

@ -63,7 +63,7 @@ Error QuickHull::build(const Vector<Vector3>& 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);

Binary file not shown.

View file

@ -5363,6 +5363,18 @@ Variant RasterizerGLES1::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar
ERR_FAIL_COND_V(!env,Variant());
return env->fx_param[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 );
};
}

View file

@ -488,6 +488,13 @@ class RasterizerGLES1 : public Rasterizer {
mutable RID_Owner<Environment> environment_owner;
struct SampledLight {
int w,h;
};
mutable RID_Owner<SampledLight> 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*/

View file

@ -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<RID> samplers;
sampled_light_owner.get_owned_list(&samplers);
Size2 debug_size(128,128);
Size2 ofs;
for (List<RID>::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;i<slight->w*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;
{

View file

@ -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> environment_owner;
struct SampledLight {
int w,h;
GLuint texture;
float multiplier;
bool is_float;
};
mutable RID_Owner<SampledLight> 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<ShadowBuffer>& 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*/

View file

@ -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

View file

@ -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

View file

@ -32,6 +32,7 @@ sources = [
"theora/video_stream_theora.cpp",
]
env.drivers_sources += sources
if env['use_theoraplayer_binary'] != "yes":
env.drivers_sources += sources

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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<<GDFunction::ADDR_BITS); //argument (stack root)
}
}
@ -1507,8 +1507,12 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
#endif
}
int new_idx = p_script->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);
}

View file

@ -250,12 +250,12 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p
ERR_FAIL_COND( script.is_null() );
const Map<StringName,int>& mi = script->debug_get_member_indices();
const Map<StringName,GDScript::MemberInfo>& mi = script->debug_get_member_indices();
for(const Map<StringName,int>::Element *E=mi.front();E;E=E->next()) {
for(const Map<StringName,GDScript::MemberInfo>::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));
}
}

View file

@ -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<ConstantNode*>(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<ConstantNode*>(subexpr);
if (cn->value.get_type()!=Variant::NIL) {
member.default_value=cn->value;
}
}
#endif
IdentifierNode *id = alloc_node<IdentifierNode>();
id->name=member.identifier;
OperatorNode *op = alloc_node<OperatorNode>();
op->op=OperatorNode::OP_ASSIGN;
op->arguments.push_back(id);
op->arguments.push_back(subexpr);
#ifdef DEBUG_ENABLED
NewLineNode *nl = alloc_node<NewLineNode>();
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<ConstantNode*>(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<ConstantNode*>(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<IdentifierNode>();
id->name=member.identifier;
OperatorNode *op = alloc_node<OperatorNode>();
op->op=OperatorNode::OP_ASSIGN;
op->arguments.push_back(id);
op->arguments.push_back(subexpr);
#ifdef DEBUG_ENABLED
NewLineNode *nl = alloc_node<NewLineNode>();
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();

View file

@ -82,6 +82,8 @@ public:
Variant default_value;
#endif
StringName identifier;
StringName setter;
StringName getter;
};
struct Constant {
StringName identifier;

View file

@ -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<StringName,GDFunction>& GDScript::debug_get_member_functions() const {
StringName GDScript::debug_get_member_by_index(int p_idx) const {
for(const Map<StringName,int>::Element *E=member_indices.front();E;E=E->next()) {
for(const Map<StringName,MemberInfo>::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<StringName,int>::Element *E = script->member_indices.find(p_name);
const Map<StringName,GDScript::MemberInfo>::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<StringName,int>::Element *E = script->member_indices.find(p_name);
const Map<StringName,GDScript::MemberInfo>::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<GDInstance*>(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<PropertyInfo> *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<String> *p_words) const {
"false" ,
"tool",
"var",
"setget",
"pass",
"and",
"or",

View file

@ -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<GDNativeClass> native;
Ref<GDScript> base;
@ -234,7 +241,7 @@ friend class GDFunctions;
Set<StringName> members; //members are just indices to the instanced script.
Map<StringName,Variant> constants;
Map<StringName,GDFunction> member_functions;
Map<StringName,int> member_indices; //members are just indices to the instanced script.
Map<StringName,MemberInfo> member_indices; //members are just indices to the instanced script.
Map<StringName,Ref<GDScript> > subclasses;
#ifdef TOOLS_ENABLED
@ -288,7 +295,7 @@ public:
bool is_tool() const { return tool; }
Ref<GDScript> get_base() const;
const Map<StringName,int>& debug_get_member_indices() const { return member_indices; }
const Map<StringName,MemberInfo>& debug_get_member_indices() const { return member_indices; }
const Map<StringName,GDFunction>& debug_get_member_functions() const; //this is debug only
StringName debug_get_member_by_index(int p_idx) const;

View file

@ -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<uint8_t> & p_buffer) {

View file

@ -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,

View file

@ -121,16 +121,16 @@ static void register_editor_plugin() {
void register_gdscript_types() {
ObjectTypeDB::register_type<GDScript>();
ObjectTypeDB::register_virtual_type<GDFunctionState>();
script_language_gd=memnew( GDScriptLanguage );
script_language_gd->init();
ScriptServer::register_language(script_language_gd);
ObjectTypeDB::register_type<GDScript>();
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<GDFunctionState>();
#ifdef TOOLS_ENABLED

View file

@ -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);

View file

@ -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<PropertyInfo> *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<String> 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;

View file

@ -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)

View file

@ -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'])

View file

@ -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'),
]

View file

@ -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"

View file

@ -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<Face3> BakedLightSampler::get_faces(uint32_t p_usage_flags) const {
return DVector<Face3>();
}
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);
}

View file

@ -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<Face3> 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

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -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<GeometryInstance>();
while(parent) {
room = parent->cast_to<Room>();
if (room)
break;
else
parent=parent->get_parent_spatial();
if (is_geom && parent->cast_to<BakedLightSampler>()) {
VS::get_singleton()->instance_geometry_set_baked_light_sampler(get_instance(),parent->cast_to<BakedLightSampler>()->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;

View file

@ -47,6 +47,7 @@ class VisualInstance : public Spatial {
RID _get_visual_instance_rid() const;
protected:

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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() {

View file

@ -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<RenderTargetTexture> 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;

View file

@ -394,6 +394,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityNotifier>();
ObjectTypeDB::register_type<VisibilityEnabler>();
ObjectTypeDB::register_type<BakedLightInstance>();
ObjectTypeDB::register_type<BakedLightSampler>();
ObjectTypeDB::register_type<WorldEnvironment>();
//scenariofx

View file

@ -23,6 +23,27 @@ DVector<uint8_t> BakedLight::get_octree() const {
return VS::get_singleton()->baked_light_get_octree(baked_light);
}
void BakedLight::set_light(const DVector<uint8_t>& p_light) {
VS::get_singleton()->baked_light_set_light(baked_light,p_light);
}
DVector<uint8_t> BakedLight::get_light() const {
return VS::get_singleton()->baked_light_get_light(baked_light);
}
void BakedLight::set_sampler_octree(const DVector<int>& p_sampler_octree) {
VS::get_singleton()->baked_light_set_sampler_octree(baked_light,p_sampler_octree);
}
DVector<int> 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();

View file

@ -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<uint8_t>& p_octree);
DVector<uint8_t> get_octree() const;
void set_light(const DVector<uint8_t>& p_light);
DVector<uint8_t> get_light() const;
void set_sampler_octree(const DVector<int>& p_sampler_octree);
DVector<int> get_sampler_octree() const;
void add_lightmap(const Ref<Texture> &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;

View file

@ -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 );
}

View file

@ -503,6 +503,7 @@ public:
VS::BakedLightMode mode;
RID octree_texture;
RID light_texture;
float color_multiplier; //used for both lightmaps and octree
Transform octree_transform;
Map<int,RID> lightmaps;
@ -514,6 +515,7 @@ public:
float lightmap_multiplier;
int octree_steps;
Vector2 octree_tex_pixel_size;
Vector2 light_tex_pixel_size;
};
struct InstanceData {
@ -521,6 +523,7 @@ public:
Transform transform;
RID skeleton;
RID material_override;
RID sampled_light;
Vector<RID> light_instances;
Vector<float> morph_values;
BakedLightData *baked_light;
@ -586,6 +589,10 @@ public:
virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0;
virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0;
/* SAMPLED LIGHT */
virtual RID sampled_light_dp_create(int p_width,int p_height)=0;
virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0;
/*MISC*/

View file

@ -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 );
};
}

View file

@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer {
mutable RID_Owner<Environment> environment_owner;
struct SampledLight {
int w,h;
};
mutable RID_Owner<SampledLight> sampled_light_owner;
struct ShadowBuffer;
struct LightInstance {
@ -713,6 +720,10 @@ public:
virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value);
virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const;
/* SAMPLED LIGHT */
virtual RID sampled_light_dp_create(int p_width,int p_height);
virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier);
/*MISC*/

View file

@ -1109,8 +1109,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
int tex_w;
int tex_h;
int light_tex_w;
int light_tex_h;
bool is16;
bool has_light_tex=false;
{
DVector<uint8_t>::Read r=p_octree.read();
tex_w = decode_uint32(&r[0]);
tex_h = decode_uint32(&r[4]);
@ -1123,7 +1127,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
baked_light->data.octree_steps=decode_uint32(&r[16]);
baked_light->data.octree_tex_pixel_size.x=1.0/tex_w;
baked_light->data.octree_tex_pixel_size.y=1.0/tex_h;
baked_light->data.texture_multiplier=decode_uint32(&r[20]);
light_tex_w=decode_uint16(&r[24]);
light_tex_h=decode_uint16(&r[26]);
print_line("ltexw "+itos(light_tex_w));
print_line("ltexh "+itos(light_tex_h));
if (light_tex_w>0 && light_tex_h>0) {
baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w;
baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h;
has_light_tex=true;
} else {
baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size;
}
baked_light->octree_aabb.pos.x=decode_float(&r[32]);
@ -1141,12 +1160,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
rasterizer->free(baked_light->data.octree_texture);
baked_light->data.octree_texture=RID();
baked_light->octree_tex_size.x=0;
baked_light->octree_tex_size.y=0;
}
}
if (baked_light->data.light_texture.is_valid()) {
if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) {
rasterizer->free(baked_light->data.light_texture);
baked_light->data.light_texture=RID();
baked_light->light_tex_size.x=0;
baked_light->light_tex_size.y=0;
}
}
if (!baked_light->data.octree_texture.is_valid()) {
baked_light->data.octree_texture=rasterizer->texture_create();
rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER);
baked_light->octree_tex_size.x=tex_w;
baked_light->octree_tex_size.y=tex_h;
}
if (!baked_light->data.light_texture.is_valid() && has_light_tex) {
baked_light->data.light_texture=rasterizer->texture_create();
rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER);
baked_light->light_tex_size.x=light_tex_w;
baked_light->light_tex_size.y=light_tex_h;
}
Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree);
@ -1159,6 +1199,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
}
DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{
@ -1174,6 +1215,67 @@ DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) c
}
}
void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) {
VS_CHANGED;
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
ERR_FAIL_COND(!baked_light);
ERR_FAIL_COND(p_light.size()==0);
int tex_w=baked_light->light_tex_size.x;
int tex_h=baked_light->light_tex_size.y;
ERR_FAIL_COND(tex_w==0 && tex_h==0);
ERR_FAIL_COND(!baked_light->data.light_texture.is_valid());
print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size()));
Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light);
rasterizer->texture_set_data(baked_light->data.light_texture,img);
}
DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>());
if (rasterizer->is_texture(baked_light->data.light_texture)) {
Image img = rasterizer->texture_get_data(baked_light->data.light_texture);
return img.get_data();
} else {
return DVector<uint8_t>();
}
}
void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) {
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
ERR_FAIL_COND(!baked_light);
baked_light->sampler=p_sampler;
}
DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const {
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
ERR_FAIL_COND_V(!baked_light,DVector<int>());
return baked_light->sampler;
}
void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){
VS_CHANGED;
@ -1192,6 +1294,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){
}
/* BAKED LIGHT SAMPLER */
RID VisualServerRaster::baked_light_sampler_create() {
BakedLightSampler * blsamp = memnew( BakedLightSampler );
RID rid = baked_light_sampler_owner.make_rid(blsamp);
_update_baked_light_sampler_dp_cache(blsamp);
return rid;
}
void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){
VS_CHANGED;
BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
ERR_FAIL_COND(!blsamp);
ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX);
blsamp->params[p_param]=p_value;
_dependency_queue_update(p_baked_light_sampler,true);
}
float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{
BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
ERR_FAIL_COND_V(!blsamp,0);
ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0);
return blsamp->params[p_param];
}
void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) {
int res = blsamp->resolution;
blsamp->dp_cache.resize(res*res*2);
Vector3 *dp_normals=blsamp->dp_cache.ptr();
for(int p=0;p<2;p++) {
float sign = p==0?1:-1;
int ofs = res*res*p;
for(int i=0;i<res;i++) {
for(int j=0;j<res;j++) {
Vector2 v(
(i/float(res))*2.0-1.0,
(j/float(res))*2.0-1.0
);
float l=v.length();
if (l>1.0) {
v/=l;
l=1.0; //clamp to avoid imaginary
}
v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function
Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z
n.y*=sign;
dp_normals[j*res+i+ofs]=n;
}
}
}
}
void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){
ERR_FAIL_COND(p_resolution<4 && p_resolution>64);
VS_CHANGED;
BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
ERR_FAIL_COND(!blsamp);
blsamp->resolution=p_resolution;
_update_baked_light_sampler_dp_cache(blsamp);
}
int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{
BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler);
ERR_FAIL_COND_V(!blsamp,0);
return blsamp->resolution;
}
/* CAMERA API */
RID VisualServerRaster::camera_create() {
@ -1943,6 +2123,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
}
if (instance->baked_light_sampler_info) {
while (instance->baked_light_sampler_info->owned_instances.size()) {
instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID());
}
if (instance->baked_light_sampler_info->sampled_light.is_valid()) {
rasterizer->free(instance->baked_light_sampler_info->sampled_light);
}
memdelete( instance->baked_light_sampler_info );
instance->baked_light_sampler_info=NULL;
}
instance->data.morph_values.clear();
}
@ -1992,6 +2186,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
//instance->portal_info = memnew(Instance::PortalInfo);
//instance->portal_info->portal=portal_owner.get(p_base);
} else if (baked_light_sampler_owner.owns(p_base)) {
instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER;
instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo);
instance->baked_light_sampler_info->sampler=baked_light_sampler_owner.get(p_base);
//instance->portal_info = memnew(Instance::PortalInfo);
//instance->portal_info->portal=portal_owner.get(p_base);
} else {
ERR_EXPLAIN("Invalid base RID for instance!")
ERR_FAIL();
@ -2607,11 +2811,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{
const Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND_V( !instance,RID() );
if (instance->baked_light)
instance->baked_light->self;
return instance->baked_light->self;
return RID();
}
void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) {
VS_CHANGED;
Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND( !instance );
if (instance->sampled_light) {
instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance);
instance->data.sampled_light=RID();
}
if(p_baked_light_sampler.is_valid()) {
Instance *sampler_instance = instance_owner.get( p_baked_light_sampler );
ERR_FAIL_COND( !sampler_instance );
ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER );
instance->sampled_light=sampler_instance;
instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance);
} else {
instance->sampled_light=NULL;
}
instance->data.sampled_light=RID();
}
RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const {
Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND_V( !instance,RID() );
if (instance->sampled_light)
return instance->sampled_light->self;
else
return RID();
}
void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){
VS_CHANGED;
@ -2747,6 +2990,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) {
pairable=true;
}
if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) {
pairable_mask=(1<<INSTANCE_BAKED_LIGHT);
pairable=true;
}
if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) {
base_type|=INSTANCE_ROOMLESS_MASK;
@ -2859,6 +3109,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) {
new_aabb=baked_light->octree_aabb;
} break;
case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: {
BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid );
ERR_FAIL_COND(!baked_light_sampler);
float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS];
new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2));
} break;
default: {}
}
@ -3762,6 +4022,17 @@ void VisualServerRaster::free( RID p_rid ) {
baked_light_owner.free(p_rid);
memdelete(baked_light);
} else if (baked_light_sampler_owner.owns(p_rid)) {
_free_attached_instances(p_rid);
BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid);
ERR_FAIL_COND(!baked_light_sampler);
//if (baked_light->data.octree_texture.is_valid())
// rasterizer->free(baked_light->data.octree_texture);
baked_light_sampler_owner.free(p_rid);
memdelete(baked_light_sampler);
} else if (camera_owner.owns(p_rid)) {
// delete te camera
@ -3813,7 +4084,9 @@ void VisualServerRaster::free( RID p_rid ) {
instance_set_room(p_rid,RID());
instance_set_scenario(p_rid,RID());
instance_geometry_set_baked_light(p_rid,RID());
instance_geometry_set_baked_light_sampler(p_rid,RID());
instance_set_base(p_rid,RID());
if (instance->data.skeleton.is_valid())
instance_attach_skeleton(p_rid,RID());
@ -4957,6 +5230,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance
//attempt to conncet portal A (will go through B anyway)
//this is a little hackish, but works fine in practice
} else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) {
if (B->base_type==INSTANCE_BAKED_LIGHT) {
SWAP(A,B);
}
ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL);
B->baked_light_sampler_info->baked_lights.insert(A);
} else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) {
if (B->base_type==INSTANCE_ROOM)
@ -5006,6 +5288,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance
self->_portal_attempt_connect(A);
self->_portal_attempt_connect(B);
} else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) {
if (B->base_type==INSTANCE_BAKED_LIGHT) {
SWAP(A,B);
}
ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER);
B->baked_light_sampler_info->baked_lights.erase(A);
} else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) {
if (B->base_type==INSTANCE_ROOM)
@ -5197,6 +5488,308 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance
}
void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) {
BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler;
int res = sampler_opts->resolution;
int dp_size = res*res*2;
Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors
Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals
const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr();
if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) {
if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) {
rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light);
}
p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution;
p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2);
}
zeromem(dp_map,sizeof(Color)*dp_size);
bool valid=false;
int samples=0;
for(Set<Instance*>::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) {
Instance *bl = E->get();
if (bl->baked_light_info->baked_light->sampler.size()==0)
continue; //not usable
Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse();
for(int i=0;i<dp_size;i++) {
dp_normals[i]=norm_xform.xform(dp_src_normals[i]).normalized();
}
//normals in place
//sample octree
float r = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_RADIUS];
float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION];
float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH];
Vector3 s = p_sampled_light->data.transform.basis.get_scale();
r*=MAX(MAX(s.x,s.y),s.z);
AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2)));
//ok got octree local AABB
DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read();
const int *rptr = rp.ptr();
int first = rptr[1];
int depth = rptr[2];
bool islinear = rptr[3]&1;
depth+=1;
AABB aabb;
aabb.pos.x=decode_float((const uint8_t*)&rptr[4]);
aabb.pos.y=decode_float((const uint8_t*)&rptr[5]);
aabb.pos.z=decode_float((const uint8_t*)&rptr[6]);
aabb.size.x=decode_float((const uint8_t*)&rptr[7]);
aabb.size.y=decode_float((const uint8_t*)&rptr[8]);
aabb.size.z=decode_float((const uint8_t*)&rptr[9]);
uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t));
int *stack_ptr=(int*)alloca(depth*sizeof(int));
AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB));
stack[0]=0;
stack_ptr[0]=first;
aabb_stack[0]=aabb;
Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5;
int stack_pos=0;
Color max_col;
//int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO];
int lalimit = sample_aabb.get_longest_axis_index();
float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit];
while(true) {
bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0;
if (aabb_stack[stack_pos].size[lalimit]<limit) {
leaf=true;
}
if (leaf) {
Vector3 from = aabb_stack[stack_pos].pos + aabb_stack[stack_pos].size * 0.5;
Vector3 norm = (from-center).normalized();
Color col;
col.r = ((rptr[ stack_ptr[stack_pos] ]&0xFFFF)/256.0);
col.g = ((rptr[ stack_ptr[stack_pos]+1 ]>>16)/256.0);
col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0);
max_col.r = MAX(max_col.r,col.r);
max_col.g = MAX(max_col.g,col.g);
max_col.b = MAX(max_col.b,col.b);
if (!islinear && p_linear_colorspace) {
col=col.to_linear();
}
float distance;
if (aabb_stack[stack_pos].has_point(center)) {
distance=0;
} else {
Vector3 support = aabb_stack[stack_pos].get_support(norm);
distance = Math::absf(norm.dot(support)-norm.dot(center));
}
if (distance>r)
distance=r;
float mult = powf(1.0-distance/r,att)*str;
if (mult>0) {
col.r*=mult;
col.g*=mult;
col.b*=mult;
for(int i=0;i<dp_size;i++) {
float mult2 = norm.dot(dp_normals[i]);
if (mult2<0)
mult2=0;
Color col2(col.r*mult2,col.g*mult2,col.b*mult2,1.0);
dp_map[i].r=MAX(dp_map[i].r,col2.r);
dp_map[i].g=MAX(dp_map[i].g,col2.g);
dp_map[i].b=MAX(dp_map[i].b,col2.b);
}
}
samples++;
//nothing is valid unless you hit a leaf
valid=true;
stack_pos--;
} else if ((stack[stack_pos]&0xFF)<8) {
int i = stack[stack_pos]&0xFF;
int base = (stack[stack_pos]>>8);
if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<<i))) {
//no bit, no test
stack[stack_pos]=(base<<8)+(i+1);
continue;
}
stack[stack_pos]=((base+1)<<8)+(i+1);
AABB child_aabb = aabb_stack[stack_pos];
child_aabb.size*=0.5;
if (i&1)
child_aabb.pos.x+=child_aabb.size.x;
if (i&2)
child_aabb.pos.y+=child_aabb.size.y;
if (i&4)
child_aabb.pos.z+=child_aabb.size.z;
if (!child_aabb.intersects(sample_aabb)) {
continue;
}
if (child_aabb.encloses(sample_aabb)) {
stack[stack_pos]=(base<<8)|8; //don't test the rest
}
stack_pos++;
ERR_FAIL_COND(stack_pos>=depth);
stack[stack_pos]=0;
stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ];
aabb_stack[stack_pos]=child_aabb;
} else {
stack_pos--;
if (stack_pos<0)
break;
}
}
}
//print_line("samples "+itos(samples) );
if (valid) {
for(int i=0;i<res;i++) {
//average seams to avoid aliasing
{
//top
int ofs1 = i;
int ofs2 = dp_size-res+i;
Color avg(
(dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
(dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
(dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
1.0
);
dp_map[ofs1]=avg;
dp_map[ofs2]=avg;
}
{
//bottom
int ofs1 = res*res-res+i;
int ofs2 = res*res+i;
Color avg(
(dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
(dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
(dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
1.0
);
dp_map[ofs1]=avg;
dp_map[ofs2]=avg;
}
{
//left
int ofs1 = i*res;
int ofs2 = res*res+(res-i-1)*res;
Color avg(
(dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
(dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
(dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
1.0
);
dp_map[ofs1]=avg;
dp_map[ofs2]=avg;
}
{
//right
int ofs1 = i*res+(res-1);
int ofs2 = res*res+(res-i-1)*res+(res-1);
Color avg(
(dp_map[ofs1].r+dp_map[ofs2].r)*0.5,
(dp_map[ofs1].g+dp_map[ofs2].g)*0.5,
(dp_map[ofs1].b+dp_map[ofs2].b)*0.5,
1.0
);
dp_map[ofs1]=avg;
dp_map[ofs2]=avg;
}
}
rasterizer->sampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0);
for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) {
F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light;
}
} else {
for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) {
F->get()->data.sampled_light=RID(); //do not use because nothing close
}
}
/*
highp vec3 vtx = vertex_interp;
vtx.z*=dual_paraboloid.y; //side to affect
vtx.z+=0.01;
dp_clip=vtx.z;
highp float len=length( vtx );
vtx=normalize(vtx);
vtx.xy/=1.0+vtx.z;
vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near);
vtx+=normalize(vtx)*0.025;
vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace
vertex_interp=vtx;
*/
}
void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) {
@ -5248,6 +5841,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
/* STEP 2 - CULL */
int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL);
light_cull_count=0;
light_samplers_culled=0;
/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
@ -5408,6 +6002,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
keep=true;
}
}
@ -5420,6 +6016,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
cull_range.min=min;
if (max>cull_range.max)
cull_range.max=max;
if (ins->sampled_light && ins->sampled_light->baked_light_sampler_info->last_pass!=render_pass) {
if (light_samplers_culled<MAX_LIGHT_SAMPLERS) {
light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light;
ins->sampled_light->baked_light_sampler_info->last_pass=render_pass;
}
}
}
}
@ -5499,7 +6102,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
}
{
{ //this should eventually change to
//assign shadows by distance to camera
SortArray<Instance*,_InstanceLightsort> sorter;
sorter.sort(light_cull_result,light_cull_count);
@ -5520,10 +6123,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
}
}
/* ENVIRONMENT */
/* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/
RID environment;
if (p_camera->env.is_valid()) //camera has more environment priority
environment=p_camera->env;
@ -5532,6 +6133,22 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
else
environment=p_scenario->fallback_environment;
/* STEP 6 - SAMPLE BAKED LIGHT */
bool islinear =false;
if (environment.is_valid()) {
islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB);
}
for(int i=0;i<light_samplers_culled;i++) {
_process_sampled_light(p_camera->transform,light_sampler_cull_result[i],islinear);
}
/* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/
rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug);
rasterizer->set_viewport(viewport_rect);
@ -5838,6 +6455,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
desired_rect.x+=p_ofs_x;
desired_rect.y+=p_ofs_y;
// if the viewport is different than the actual one, change it
if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x ||
@ -5847,7 +6465,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
viewport_rect=desired_rect;
rasterizer->set_viewport(viewport_rect);
rasterizer->set_viewport(viewport_rect);
}
@ -5995,7 +6613,14 @@ void VisualServerRaster::_draw_viewports() {
int window_w = OS::get_singleton()->get_video_mode(E->get()).width;
int window_h = OS::get_singleton()->get_video_mode(E->get()).height;
_draw_viewport(vp,0,0,window_w,window_h);
Rect2 r(0,0,vp->rect.width,vp->rect.height);
if (r.size.width==0)
r.size.width=window_w;
if (r.size.height==0)
r.size.height=window_w;
_draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height);
}

View file

@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer {
MAX_LIGHTS_CULLED=256,
MAX_ROOM_CULL=32,
MAX_EXTERIOR_PORTALS=128,
MAX_LIGHT_SAMPLERS=256,
INSTANCE_ROOMLESS_MASK=(1<<20)
@ -90,12 +91,29 @@ class VisualServerRaster : public VisualServer {
struct BakedLight {
Rasterizer::BakedLightData data;
DVector<int> sampler;
AABB octree_aabb;
Size2i octree_tex_size;
Size2i light_tex_size;
};
struct BakedLightSampler {
float params[BAKED_LIGHT_SAMPLER_MAX];
int resolution;
Vector<Vector3> dp_cache;
BakedLightSampler() {
params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0;
params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0;
params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0;
params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1;
resolution=16;
}
};
void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp);
struct Camera {
enum Type {
@ -169,6 +187,7 @@ class VisualServerRaster : public VisualServer {
List<Instance*>::Element *RE;
Instance *baked_light;
List<Instance*>::Element *BLE;
Instance *sampled_light;
bool exterior;
uint64_t last_render_pass;
@ -179,6 +198,8 @@ class VisualServerRaster : public VisualServer {
InstanceSet lights;
bool light_cache_dirty;
struct RoomInfo {
Transform affine_inverse;
@ -235,6 +256,23 @@ class VisualServerRaster : public VisualServer {
Transform affine_inverse;
List<Instance*> owned_instances;
};
struct BakedLightSamplerInfo {
Set<Instance*> baked_lights;
Set<Instance*> owned_instances;
BakedLightSampler *sampler;
int resolution;
Vector<Color> light_bufer;
RID sampled_light;
uint64_t last_pass;
Transform xform; // viewspace normal to lightspace, might not use one.
BakedLightSamplerInfo() {
sampler=NULL;
last_pass=0;
resolution=0;
}
};
struct ParticlesInfo {
@ -247,6 +285,7 @@ class VisualServerRaster : public VisualServer {
ParticlesInfo *particles_info;
PortalInfo * portal_info;
BakedLightInfo * baked_light_info;
BakedLightSamplerInfo * baked_light_sampler_info;
Instance() {
@ -282,6 +321,8 @@ class VisualServerRaster : public VisualServer {
baked_light=NULL;
baked_light_info=NULL;
baked_light_sampler_info=NULL;
sampled_light=NULL;
BLE=NULL;
light_cache_dirty=true;
@ -603,6 +644,9 @@ class VisualServerRaster : public VisualServer {
int exterior_portal_cull_count;
bool exterior_visited;
Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS];
int light_samplers_culled;
Instance *room_cull_result[MAX_ROOM_CULL];
int room_cull_count;
bool room_cull_enabled;
@ -638,6 +682,7 @@ class VisualServerRaster : public VisualServer {
mutable RID_Owner<Portal> portal_owner;
mutable RID_Owner<BakedLight> baked_light_owner;
mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner;
mutable RID_Owner<Camera> camera_owner;
mutable RID_Owner<Viewport> viewport_owner;
@ -658,6 +703,8 @@ class VisualServerRaster : public VisualServer {
bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to);
void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal);
void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL);
void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace);
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity);
void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform);
@ -953,12 +1000,28 @@ public:
virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree);
virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const;
virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light);
virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const;
virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler);
virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const;
virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier);
virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const;
virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id);
virtual void baked_light_clear_lightmaps(RID p_baked_light);
/* BAKED LIGHT SAMPLER */
virtual RID baked_light_sampler_create();
virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value);
virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const;
virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution);
virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const;
/* CAMERA API */
virtual RID camera_create();
@ -1096,6 +1159,9 @@ public:
virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light);
virtual RID instance_geometry_get_baked_light(RID p_instance) const;
virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler);
virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const;
virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id);
virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const;

View file

@ -909,6 +909,12 @@ public:
FUNC2(baked_light_set_octree,RID,DVector<uint8_t>);
FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID);
FUNC2(baked_light_set_light,RID,DVector<uint8_t>);
FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID);
FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&);
FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID);
FUNC2(baked_light_set_lightmap_multiplier,RID,float);
FUNC1RC(float,baked_light_get_lightmap_multiplier,RID);
@ -916,6 +922,14 @@ public:
FUNC1(baked_light_clear_lightmaps,RID);
FUNC0R(RID,baked_light_sampler_create);
FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float );
FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam );
FUNC2(baked_light_sampler_set_resolution,RID,int);
FUNC1RC(int,baked_light_sampler_get_resolution,RID);
/* CAMERA API */
FUNC0R(RID,camera_create);
@ -1055,6 +1069,9 @@ public:
FUNC2(instance_geometry_set_baked_light,RID, RID );
FUNC1RC(RID,instance_geometry_get_baked_light,RID);
FUNC2(instance_geometry_set_baked_light_sampler,RID, RID );
FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID);
FUNC2(instance_geometry_set_baked_light_texture_index,RID, int);
FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID);

View file

@ -590,12 +590,35 @@ public:
virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0;
virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0;
virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0;
virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0;
virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0;
virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0;
virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0;
virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0;
virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0;
virtual void baked_light_clear_lightmaps(RID p_baked_light)=0;
/* BAKED LIGHT SAMPLER */
virtual RID baked_light_sampler_create()=0;
enum BakedLightSamplerParam {
BAKED_LIGHT_SAMPLER_RADIUS,
BAKED_LIGHT_SAMPLER_STRENGTH,
BAKED_LIGHT_SAMPLER_ATTENUATION,
BAKED_LIGHT_SAMPLER_DETAIL_RATIO,
BAKED_LIGHT_SAMPLER_MAX
};
virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0;
virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0;
virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0;
virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0;
/* CAMERA API */
@ -824,7 +847,8 @@ public:
INSTANCE_ROOM,
INSTANCE_PORTAL,
INSTANCE_BAKED_LIGHT,
INSTANCE_BAKED_LIGHT_SAMPLER,
INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES)
};
@ -898,9 +922,13 @@ public:
virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0;
virtual RID instance_geometry_get_baked_light(RID p_instance) const=0;
virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0;
virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0;
virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0;
virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0;
virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0;
virtual bool instance_light_is_enabled(RID p_instance) const=0;

View file

@ -2106,6 +2106,8 @@ void Collada::_parse_animation_clip(XMLParser& parser) {
if (parser.has_attribute("name"))
clip.name=parser.get_attribute_value("name");
else if (parser.has_attribute("id"))
clip.name=parser.get_attribute_value("id");
if (parser.has_attribute("start"))
clip.begin=parser.get_attribute_value("start").to_double();
if (parser.has_attribute("end"))

View file

@ -337,7 +337,7 @@ for file in input_list:
class_names.sort()
make_class_list(class_names, 3)
make_class_list(class_names, 2)
for cn in class_names:
c = classes[cn]

View file

@ -4,8 +4,17 @@
#include <cmath>
#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<Texture>&
image.convert(Image::FORMAT_RGBA);
}
if (imgtex->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR) {
Image copy = image;
copy.srgb_to_linear();
image=copy;
}
DVector<uint8_t> dvt=image.get_data();
DVector<uint8_t>::Read r=dvt.read();
MeshTexture mt;
@ -105,8 +120,13 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& 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;li<lz;li++) {
for(int ci=0;ci<8;ci++) {
child->light[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 (dist<r) {
//avoid accumulaiton of light on corners
//plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
plot_light=Color(0,0,0,0);
skip-true;
} else {
@ -1181,12 +1244,12 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
double r2 = double(rand())/RAND_MAX;
double r3 = double(rand())/RAND_MAX;
Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.25)).normalized();
float d =_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,false,true);
r = plot_size*cell_size*0.7;
float d =_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,false,true);
r = plot_size*cell_size*ao_radius;
if (d>0 && d<r) {
//avoid accumulaiton of light on corners
//plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
plot_light=Color(0,0,0,0);
skip=true;
} else {
//plot_light=Color(0,0,0,0);
@ -1195,11 +1258,9 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
}
if (!p_first_bounce || lights[p_light_index].bake_direct) {
Plane plane(r_point,r_normal);
//print_line(String(plot_light)+String(" ")+rtos(att));
_plot_light(p_light_index,r_point,aabb,plot_light,plane);
}
Plane plane(r_point,r_normal);
if (!skip)
_plot_light(thread_stack,r_point,aabb,plot_light,tint_light,!(!p_first_bounce || p_bake_direct),plane);
return dist;
@ -1305,9 +1366,87 @@ void BakedLightBaker::_make_octree_texture() {
//ok let's try to just create a texture
int otex_w=256;
while (true) {
uint32_t oct_idx=leaf_list;
int row=0;
print_line("begin at row "+itos(row));
int longest_line_reused=0;
int col=0;
int processed=0;
//reset
while(oct_idx) {
BakedLightBaker::Octant *oct = &octants[oct_idx];
oct->texture_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<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally
otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally
Vector3 lattice_cell_size=octree_aabb.size;
for(int i=0;i<lattice_size;i++) {
@ -1320,64 +1459,7 @@ void BakedLightBaker::_make_octree_texture() {
//let's plot the leafs first, given the octree is not so obvious which size it will have
int row=4+4*(1<<lattice_size);
uint32_t oct_idx=leaf_list;
//untag
while(oct_idx) {
BakedLightBaker::Octant *oct = &octants[oct_idx];
//0,0 also means unprocessed
oct->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<BakedLight> &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;i<baked_light->get_lightmaps_count();i++) {
@ -1651,13 +1762,134 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) {
}
void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) {
void BakedLightBaker::update_octree_sampler(DVector<int> &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<int> 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<int>::Write w = p_sampler.write();
int ss = tmp_smp.size();
for(int i=0;i<ss;i++) {
w[i]=tmp_smp[i];
}
first_bake_to_map=false;
}
double gamma = baked_light->get_gamma_adjust();
double mult = baked_light->get_energy_multiplier();
float saturation = baked_light->get_saturation();
DVector<int>::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<uint8_t> &p_octree,DVector<uint8_t> &p_light) {
int len = baked_octree_texture_w*baked_octree_texture_h*4;
p_image.resize(len);
DVector<uint8_t>::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<uint8_t>::Write w = p_octree.write();
zeromem(w.ptr(),len);
DVector<uint8_t>::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<uint8_t> &p_image) {
w[i+3]=0xFF;
}
for(int i=0;i<ilen;i+=4) {
iw[i+0]=0xFF;
iw[i+1]=0;
iw[i+2]=0xFF;
iw[i+3]=0xFF;
}
float multiplier=1.0;
if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
@ -1678,6 +1917,9 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) {
encode_float(1<<lattice_size,&w[12]);
encode_uint32(octree_depth-lattice_size,&w[16]);
encode_uint32(multiplier,&w[20]);
encode_uint16(baked_light_texture_w,&w[24]); //if present, use the baked light texture
encode_uint16(baked_light_texture_h,&w[26]);
encode_uint32(0,&w[28]); //baked light texture format
encode_float(octree_aabb.pos.x,&w[32]);
encode_float(octree_aabb.pos.y,&w[36]);
@ -1690,6 +1932,7 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &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<uint8_t> &p_image) {
baked_octree_texture_w*8+baked_octree_texture_w*4+4,
};
Vector<double> 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<double> norm_arr;
norm_arr.resize(lights.size());
for(int i=0;i<lights.size();i++) {
@ -1711,39 +1965,43 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &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;i<octant_count;i++) {
Octant &oct=octants[i];
if (oct.texture_x==0 && oct.texture_y==0)
continue;
int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2;
if (oct.leaf) {
int ofs = (oct.texture_y * baked_light_texture_w + oct.texture_x)<<2;
ERR_CONTINUE(ofs<0 || ofs >ilen);
//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<lz;k++) {
r+=oct.light[k].accum[j][0]*normptr[k];
g+=oct.light[k].accum[j][1]*normptr[k];
b+=oct.light[k].accum[j][2]*normptr[k];
}
float r=oct.light_accum[j][0]*norm;
float g=oct.light_accum[j][1]*norm;
float b=oct.light_accum[j][2]*norm;
r=pow(r*mult,gamma);
g=pow(g*mult,gamma);
b=pow(b*mult,gamma);
double gray = (r+g+b)/3.0;
r = gray + (r-gray)*saturation;
g = gray + (g-gray)*saturation;
b = gray + (b-gray)*saturation;
float ic[3]={
r,
g,
@ -1757,6 +2015,8 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &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<threads.size();i++) {
threads[i]=Thread::create(_bake_thread_func,this);
}
}
void BakedLightBaker::_stop_thread() {
if (thread==NULL)
if (threads.size()==0)
return;
bake_thread_exit=true;
Thread::wait_to_finish(thread);
thread=NULL;
for(int i=0;i<threads.size();i++) {
Thread::wait_to_finish(threads[i]);
}
threads.clear();
}
void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) {
uint8_t *ptr = &image[(y*width+x)*4];
int lc = lights.size();
//int lc = lights.size();
double norm = 1.0/double(total_rays);
Color color;
@ -1888,11 +2160,9 @@ void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int heigh
for(int i=0;i<8;i++) {
for(int j=0;j<lc;j++) {
cols[i].x+=octant.light[j].accum[i][0]*p_norm_ptr[j];
cols[i].y+=octant.light[j].accum[i][1]*p_norm_ptr[j];
cols[i].z+=octant.light[j].accum[i][2]*p_norm_ptr[j];
}
cols[i].x+=octant.light_accum[i][0]*norm;
cols[i].y+=octant.light_accum[i][1]*norm;
cols[i].z+=octant.light_accum[i][2]*norm;
}
@ -2355,12 +2625,13 @@ void BakedLightBaker::clear() {
memdelete_arr(octantptr_stack);
if (bvh_stack)
memdelete_arr(bvh_stack);
/*
* ???
for(int i=0;i<octant_pool.size();i++) {
if (octant_pool[i].leaf) {
memdelete_arr( octant_pool[i].light );
} Vector<double> norm_arr;
norm_arr.resize(lights.size());
//if (octant_pool[i].leaf) {
// memdelete_arr( octant_pool[i].light );
//} Vector<double> norm_arr;
//norm_arr.resize(lights.size());
for(int i=0;i<lights.size();i++) {
norm_arr[i] = 1.0/get_normalization(i);
@ -2368,6 +2639,7 @@ void BakedLightBaker::clear() {
const double *normptr=norm_arr.ptr();
}
*/
octant_pool.clear();
octant_pool_size=0;
bvh=NULL;
@ -2388,8 +2660,9 @@ void BakedLightBaker::clear() {
baked_octree_texture_h=0;
paused=false;
baking=false;
thread=NULL;
bake_thread_exit=false;
first_bake_to_map=true;
baked_light=Ref<BakedLight>();
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;
}

View file

@ -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<Vector3,Vector3> endpoint_normal;
Map<Vector3,uint64_t> 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<Ref<Material>,MeshMaterial*> mat_map;
Map<Ref<Texture>,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<Thread*> 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<BakedLight>& 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<uint8_t> &p_image);
void update_octree_sampler(DVector<int> &p_sampler);
void update_octree_images(DVector<uint8_t> &p_octree,DVector<uint8_t> &p_light);
Ref<BakedLight> get_baked_light() { return baked_light; }

View file

@ -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

View file

@ -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);
}

View file

@ -23,6 +23,8 @@ class BakedLightEditor : public Control {
float update_timeout;
DVector<uint8_t> octree_texture;
DVector<uint8_t> light_texture;
DVector<int> 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;

View file

@ -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<<GIZMO_GRID_LAYER);
uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx);//|(1<<GIZMO_GRID_LAYER);
for(int i=0;i<3;i++) {
move_gizmo_instance[i]=VS::get_singleton()->instance_create();

View file

@ -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)):