diff options
author | Juan Linietsky <reduzio@gmail.com> | 2016-11-24 20:46:55 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2016-11-24 20:46:55 -0300 |
commit | a732708b9dad4ebc118a0ce854f950c6becb984c (patch) | |
tree | 4e740d30a2449e065462bc408e23536d5270ca0e | |
parent | 69c30709ec6908e0960707501cc7fea58eb64f01 (diff) |
Blend shapes using transform feedback (GPU)
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 11 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 401 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 72 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 23 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.h | 10 | ||||
-rw-r--r-- | drivers/gles3/shaders/SCsub | 1 | ||||
-rw-r--r-- | drivers/gles3/shaders/blend_shape.glsl | 197 | ||||
-rwxr-xr-x | methods.py | 39 | ||||
-rw-r--r-- | scene/resources/mesh.cpp | 6 | ||||
-rw-r--r-- | scene/resources/mesh.h | 18 | ||||
-rw-r--r-- | scene/resources/surface_tool.cpp | 38 | ||||
-rw-r--r-- | servers/visual/rasterizer.h | 3 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.cpp | 27 | ||||
-rw-r--r-- | servers/visual_server.cpp | 12 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_import_collada.cpp | 28 | ||||
-rw-r--r-- | tools/editor/plugins/script_editor_plugin.cpp | 2 |
16 files changed, 726 insertions, 162 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 7a0e21b620..9de441c2bb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1111,7 +1111,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { case VS::INSTANCE_MESH: { RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface*>(e->geometry); - glBindVertexArray(s->array_id); // everything is so easy nowadays + + if (s->morph_targets.size() && e->instance->morph_values.size()) { + //blend shapes, use transform feedback + storage->mesh_render_blend_shapes(s,e->instance->morph_values.ptr()); + //rebind shader + state.scene_shader.bind(); + } else { + + glBindVertexArray(s->array_id); // everything is so easy nowadays + } } break; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index a618953b86..559f733e4d 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2274,8 +2274,8 @@ void RasterizerStorageGLES3::_update_material(Material* material) { material->can_cast_shadow_cache=can_cast_shadow; material->is_animated_cache=is_animated; - for(Map<Instantiable*,int>::Element *E=material->instantiable_owners.front();E;E=E->next()) { - E->key()->instance_material_change_notify(); + for(Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) { + E->key()->material_changed_notify(); } for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) { @@ -2379,32 +2379,32 @@ void RasterizerStorageGLES3::_update_material(Material* material) { } -void RasterizerStorageGLES3::_material_add_instantiable(RID p_material,Instantiable *p_instantiable) { +void RasterizerStorageGLES3::_material_add_geometry(RID p_material,Geometry *p_geometry) { Material * material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - Map<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable); + Map<Geometry*,int>::Element *I = material->geometry_owners.find(p_geometry); if (I) { I->get()++; } else { - material->instantiable_owners[p_instantiable]=1; + material->geometry_owners[p_geometry]=1; } } -void RasterizerStorageGLES3::_material_remove_instantiable(RID p_material,Instantiable *p_instantiable) { +void RasterizerStorageGLES3::_material_remove_geometry(RID p_material,Geometry *p_geometry) { Material * material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - Map<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable); + Map<Geometry*,int>::Element *I = material->geometry_owners.find(p_geometry); ERR_FAIL_COND(!I); I->get()--; if (I->get()==0) { - material->instantiable_owners.erase(I); + material->geometry_owners.erase(I); } } @@ -2446,18 +2446,15 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P bool has_morph = p_blend_shapes.size(); - Surface::Attrib attribs[VS::ARRAY_MAX],morph_attribs[VS::ARRAY_MAX]; + Surface::Attrib attribs[VS::ARRAY_MAX]; int stride=0; - int morph_stride=0; for(int i=0;i<VS::ARRAY_MAX;i++) { if (! (p_format&(1<<i) ) ) { attribs[i].enabled=false; - morph_attribs[i].enabled=false; attribs[i].integer=false; - morph_attribs[i].integer=false; continue; } @@ -2466,14 +2463,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].index=i; attribs[i].integer=false; - if (has_morph) { - morph_attribs[i].enabled=true; - morph_attribs[i].offset=morph_stride; - morph_attribs[i].index=i+8; - } else { - morph_attribs[i].enabled=false; - } - switch(i) { case VS::ARRAY_VERTEX: { @@ -2494,13 +2483,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; - if (has_morph) { - //morph - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=attribs[i].size*4; - } } break; case VS::ARRAY_NORMAL: { @@ -2516,13 +2498,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; } - if (has_morph) { - //morph - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=12; - } + } break; case VS::ARRAY_TANGENT: { @@ -2539,12 +2515,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; } - if (has_morph) { - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=16; - } } break; case VS::ARRAY_COLOR: { @@ -2561,12 +2531,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; } - if (has_morph) { - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=16; - } } break; case VS::ARRAY_TEX_UV: { @@ -2583,12 +2547,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; - if (has_morph) { - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=8; - } } break; case VS::ARRAY_TEX_UV2: { @@ -2604,12 +2562,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P } attribs[i].normalized=GL_FALSE; - if (has_morph) { - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=8; - } + } break; case VS::ARRAY_BONES: { @@ -2627,12 +2580,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; attribs[i].integer=true; - if (has_morph) { - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_UNSIGNED_SHORT; - morph_stride+=8; - } + } break; case VS::ARRAY_WEIGHTS: { @@ -2650,12 +2598,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P attribs[i].normalized=GL_FALSE; } - if (has_morph) { - morph_attribs[i].normalized=GL_FALSE; - morph_attribs[i].size=attribs[i].size; - morph_attribs[i].type=GL_FLOAT; - morph_stride+=8; - } } break; case VS::ARRAY_INDEX: { @@ -2678,9 +2620,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P for(int i=0;i<VS::ARRAY_MAX-1;i++) { attribs[i].stride=stride; - if (has_morph) { - morph_attribs[i].stride=morph_stride; - } } //validate sizes @@ -2731,7 +2670,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P for(int i=0;i<VS::ARRAY_MAX;i++) { surface->attribs[i]=attribs[i]; - surface->morph_attribs[i]=morph_attribs[i]; } { @@ -2763,12 +2701,11 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P glGenVertexArrays(1,&surface->array_id); glBindVertexArray(surface->array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } else { + } else if (i==1) { //for instancing draw (can be changed and no one cares) glGenVertexArrays(1,&surface->instancing_array_id); glBindVertexArray(surface->instancing_array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } @@ -2816,17 +2753,17 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P glBindVertexArray(mt.array_id); glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id); - for(int i=0;i<VS::ARRAY_MAX-1;i++) { + for(int j=0;j<VS::ARRAY_MAX-1;j++) { - if (!attribs[i].enabled) + if (!attribs[j].enabled) continue; - if (attribs[i].integer) { - glVertexAttribIPointer(attribs[i].index,attribs[i].size,attribs[i].type,attribs[i].stride,((uint8_t*)0)+attribs[i].offset); + if (attribs[j].integer) { + glVertexAttribIPointer(attribs[j].index,attribs[j].size,attribs[j].type,attribs[j].stride,((uint8_t*)0)+attribs[j].offset); } else { - glVertexAttribPointer(attribs[i].index,attribs[i].size,attribs[i].type,attribs[i].normalized,attribs[i].stride,((uint8_t*)0)+attribs[i].offset); + glVertexAttribPointer(attribs[j].index,attribs[j].size,attribs[j].type,attribs[j].normalized,attribs[j].stride,((uint8_t*)0)+attribs[j].offset); } - glEnableVertexAttribArray(attribs[i].index); + glEnableVertexAttribArray(attribs[j].index); } @@ -2889,13 +2826,13 @@ void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface return; if (mesh->surfaces[p_surface]->material.is_valid()) { - _material_remove_instantiable(mesh->surfaces[p_surface]->material,mesh); + _material_remove_geometry(mesh->surfaces[p_surface]->material,mesh->surfaces[p_surface]); } mesh->surfaces[p_surface]->material=p_material; if (mesh->surfaces[p_surface]->material.is_valid()) { - _material_add_instantiable(mesh->surfaces[p_surface]->material,mesh); + _material_add_geometry(mesh->surfaces[p_surface]->material,mesh->surfaces[p_surface]); } mesh->instance_material_change_notify(); @@ -3067,7 +3004,7 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ Surface *surface = mesh->surfaces[p_surface]; if (surface->material.is_valid()) { - _material_remove_instantiable(surface->material,mesh); + _material_remove_geometry(surface->material,mesh->surfaces[p_surface]); } glDeleteBuffers(1,&surface->vertex_id); @@ -3241,6 +3178,227 @@ void RasterizerStorageGLES3::mesh_clear(RID p_mesh){ } } +void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, float *p_weights) { + + glBindVertexArray(s->array_id); + + BlendShapeShaderGLES3::Conditionals cond[VS::ARRAY_MAX-1]={ + BlendShapeShaderGLES3::ENABLE_NORMAL, //will be ignored + BlendShapeShaderGLES3::ENABLE_NORMAL, + BlendShapeShaderGLES3::ENABLE_TANGENT, + BlendShapeShaderGLES3::ENABLE_COLOR, + BlendShapeShaderGLES3::ENABLE_UV, + BlendShapeShaderGLES3::ENABLE_UV2, + BlendShapeShaderGLES3::ENABLE_SKELETON, + BlendShapeShaderGLES3::ENABLE_SKELETON, + }; + + int stride=0; + + if (s->format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + stride=2*4; + } else { + stride=3*4; + } + + static const int sizes[VS::ARRAY_MAX-1]={ + 3*4, + 3*4, + 4*4, + 4*4, + 2*4, + 2*4, + 4*4, + 4*4 + }; + + for(int i=1;i<VS::ARRAY_MAX-1;i++) { + shaders.blend_shapes.set_conditional(cond[i],s->format&(1<<i)); //enable conditional for format + if (s->format&(1<<i)) { + stride+=sizes[i]; + } + } + + + //copy all first + float base_weight=1.0; + + int mtc = s->morph_targets.size(); + + if (s->mesh->morph_target_mode==VS::MORPH_MODE_NORMALIZED) { + + for(int i=0;i<mtc;i++) { + base_weight-=p_weights[i]; + } + } + + + + shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND,false); //first pass does not blend + shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::USE_2D_VERTEX,s->format&VS::ARRAY_FLAG_USE_2D_VERTICES); //use 2D vertices if needed + + shaders.blend_shapes.bind(); + + shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT,base_weight); + glEnable(GL_RASTERIZER_DISCARD); + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[0]); + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,s->array_len); + glEndTransformFeedback(); + + + shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND,true); //first pass does not blend + shaders.blend_shapes.bind(); + + for(int ti=0;ti<mtc;ti++) { + float weight = p_weights[ti]; + + if (weight<0.001) //not bother with this one + continue; + + glBindVertexArray(s->morph_targets[ti].array_id); + glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[1]); + + shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT,weight); + + int ofs=0; + for(int i=0;i<VS::ARRAY_MAX-1;i++) { + + if (s->format&(1<<i)) { + glEnableVertexAttribArray(i+8); + switch(i) { + + case VS::ARRAY_VERTEX: { + if (s->format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + } else { + glVertexAttribPointer(i+8,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } + } break; + case VS::ARRAY_NORMAL: { + glVertexAttribPointer(i+8,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } break; + case VS::ARRAY_TANGENT: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_COLOR: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_TEX_UV: { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_TEX_UV2: { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_BONES: { + glVertexAttribIPointer(i+8,4,GL_UNSIGNED_INT,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_WEIGHTS: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + } + + } else { + glDisableVertexAttribArray(i+8); + } + } + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,s->array_len); + glEndTransformFeedback(); + + + SWAP(resources.transform_feedback_buffers[0],resources.transform_feedback_buffers[1]); + + } + + glDisable(GL_RASTERIZER_DISCARD); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); + + + glBindVertexArray(resources.transform_feedback_array); + glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); + + int ofs=0; + for(int i=0;i<VS::ARRAY_MAX-1;i++) { + + if (s->format&(1<<i)) { + glEnableVertexAttribArray(i); + switch(i) { + + case VS::ARRAY_VERTEX: { + if (s->format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + } else { + glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } + } break; + case VS::ARRAY_NORMAL: { + glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } break; + case VS::ARRAY_TANGENT: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_COLOR: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_TEX_UV: { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_TEX_UV2: { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_BONES: { + glVertexAttribIPointer(i,4,GL_UNSIGNED_INT,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_WEIGHTS: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + } + + } else { + glDisableVertexAttribArray(i); + } + } + + if (s->index_array_len) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); + } + +} + /* MULTIMESH API */ @@ -3896,7 +4054,6 @@ void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton,int p_bones,bool p skeleton_update_list.add(&skeleton->update_list); } - skeleton->instance_change_notify(); } @@ -4017,7 +4174,10 @@ void RasterizerStorageGLES3::update_dirty_skeletons() { glBufferSubData(GL_UNIFORM_BUFFER,0,skeleton->bones.size()*sizeof(float),skeleton->bones.ptr()); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - skeleton->instance_change_notify(); + + for (Set<RasterizerScene::InstanceBase*>::Element *E=skeleton->instances.front();E;E=E->next()) { + E->get()->base_changed(); + } skeleton_update_list.remove(skeleton_update_list.first()); } @@ -4505,6 +4665,23 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color } +void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->instances.insert(p_instance); +} + +void RasterizerStorageGLES3::instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->instances.erase(p_instance); +} + + void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance) { Instantiable *inst=NULL; @@ -4530,9 +4707,6 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: ERR_FAIL_COND(!inst); } break; default: { - if (skeleton_owner.owns(p_base)) { - inst=skeleton_owner.getornull(p_base); - } if (!inst) { ERR_FAIL(); } @@ -4550,7 +4724,6 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce case VS::INSTANCE_MESH: { inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); - } break; case VS::INSTANCE_MULTIMESH: { inst = multimesh_owner.getornull(p_base); @@ -4569,9 +4742,7 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; default: { - if (skeleton_owner.owns(p_base)) { - inst=skeleton_owner.getornull(p_base); - } + if (!inst) { ERR_FAIL(); } @@ -5134,6 +5305,26 @@ bool RasterizerStorageGLES3::free(RID p_rid){ glDeleteBuffers(1,&material->ubo_id); } + //remove from owners + for (Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) { + + Geometry *g = E->key(); + g->material=RID(); + } + for (Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) { + RasterizerScene::InstanceBase*ins=E->key(); + if (ins->material_override==p_rid) { + ins->material_override=RID(); + } + + for(int i=0;i<ins->materials.size();i++) { + if (ins->materials[i]==p_rid) { + ins->materials[i]=RID(); + } + } + + } + material_owner.free(p_rid); memdelete(material); @@ -5144,6 +5335,11 @@ bool RasterizerStorageGLES3::free(RID p_rid){ if (skeleton->update_list.in_list()) { skeleton_update_list.remove(&skeleton->update_list); } + + for (Set<RasterizerScene::InstanceBase*>::Element *E=skeleton->instances.front();E;E=E->next()) { + E->get()->skeleton=RID(); + } + skeleton_allocate(p_rid,0,false); skeleton_owner.free(p_rid); memdelete(skeleton); @@ -5370,6 +5566,23 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } + + { + //transform feedback buffers + uint32_t xf_feedback_size = GLOBAL_DEF("rendering/gles3/blend_shape_max_buffer_size_kb",4096); + for(int i=0;i<2;i++) { + + glGenBuffers(1,&resources.transform_feedback_buffers[i]); + glBindBuffer(GL_ARRAY_BUFFER,resources.transform_feedback_buffers[i]); + glBufferData(GL_ARRAY_BUFFER,xf_feedback_size*1024,NULL,GL_STREAM_DRAW); + } + + shaders.blend_shapes.init();; + + glGenVertexArrays(1,&resources.transform_feedback_array); + + } + shaders.cubemap_filter.init(); glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 623962bf61..361e738af5 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -6,6 +6,7 @@ #include "shader_gles3.h" #include "shaders/copy.glsl.h" #include "shaders/canvas.glsl.h" +#include "shaders/blend_shape.glsl.h" #include "shaders/cubemap_filter.glsl.h" #include "self_list.h" #include "shader_compiler_gles3.h" @@ -65,6 +66,8 @@ public: CubemapFilterShaderGLES3 cubemap_filter; + BlendShapeShaderGLES3 blend_shapes; + ShaderCompilerGLES3::IdentifierActions actions_canvas; ShaderCompilerGLES3::IdentifierActions actions_scene; } shaders; @@ -79,6 +82,9 @@ public: GLuint quadie; GLuint quadie_array; + GLuint transform_feedback_buffers[2]; + GLuint transform_feedback_array; + } resources; struct Info { @@ -133,8 +139,33 @@ public: } }; + struct GeometryOwner : public Instantiable { + + virtual ~GeometryOwner() {} + }; + struct Geometry : Instantiable { + + enum Type { + GEOMETRY_INVALID, + GEOMETRY_SURFACE, + GEOMETRY_IMMEDIATE, + GEOMETRY_MULTISURFACE, + }; + + + Type type; + RID material; + uint64_t last_pass; + uint32_t index; + virtual void material_changed_notify() {} + Geometry() { + last_pass=0; + index=0; + } + + }; @@ -384,7 +415,7 @@ public: uint32_t index; uint64_t last_pass; - Map<Instantiable*,int> instantiable_owners; + Map<Geometry*,int> geometry_owners; Map<RasterizerScene::InstanceBase*,int> instance_owners; bool can_cast_shadow_cache; @@ -404,8 +435,8 @@ public: mutable SelfList<Material>::List _material_dirty_list; void _material_make_dirty(Material *p_material) const; - void _material_add_instantiable(RID p_material,Instantiable *p_instantiable); - void _material_remove_instantiable(RID p_material, Instantiable *p_instantiable); + void _material_add_geometry(RID p_material,Geometry *p_instantiable); + void _material_remove_geometry(RID p_material, Geometry *p_instantiable); mutable RID_Owner<Material> material_owner; @@ -433,31 +464,9 @@ public: /* MESH API */ - struct Geometry : Instantiable { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_IMMEDIATE, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - uint64_t last_pass; - uint32_t index; - Geometry() { - last_pass=0; - index=0; - } - }; - struct GeometryOwner : public Instantiable { - - virtual ~GeometryOwner() {} - }; struct Mesh; struct Surface : public Geometry { @@ -475,7 +484,7 @@ public: }; Attrib attribs[VS::ARRAY_MAX]; - Attrib morph_attribs[VS::ARRAY_MAX]; + Mesh *mesh; @@ -512,6 +521,10 @@ public: bool active; + virtual void material_changed_notify() { + mesh->instance_material_change_notify(); + } + Surface() { array_byte_size=0; @@ -590,6 +603,8 @@ public: virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const; virtual void mesh_clear(RID p_mesh); + void mesh_render_blend_shapes(Surface *s, float *p_weights); + /* MULTIMESH API */ struct MultiMesh : public GeometryOwner { @@ -699,12 +714,13 @@ public: /* SKELETON API */ - struct Skeleton : Instantiable { + struct Skeleton : RID_Data { int size; bool use_2d; Vector<float> bones; //4x3 or 4x2 depending on what is needed GLuint ubo; SelfList<Skeleton> update_list; + Set<RasterizerScene::InstanceBase*> instances; //instances using skeleton Skeleton() : update_list(this) { size=0; @@ -843,6 +859,8 @@ public: virtual void portal_set_disable_distance(RID p_portal, float p_distance); virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 78f35c493a..d29927b137 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -502,6 +502,25 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name ); } + //if feedback exists, set it up + + if (feedback_count) { + Vector<const char*> feedback; + for(int i=0;i<feedback_count;i++) { + + if (feedbacks[i].conditional==-1 || (1<<feedbacks[i].conditional)&conditional_version.version) { + //conditional for this feedback is enabled + print_line("tf varying: "+itos(feedback.size())+" "+String(feedbacks[i].name)); + feedback.push_back(feedbacks[i].name); + } + } + + if (feedback.size()) { + glTransformFeedbackVaryings(v.id,feedback.size(),feedback.ptr(),GL_INTERLEAVED_ATTRIBS ); + } + + } + glLinkProgram(v.id); glGetProgramiv(v.id, GL_LINK_STATUS, &status); @@ -604,7 +623,7 @@ GLint ShaderGLES3::get_uniform_location(const String& p_name) const { } -void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start) { +void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback* p_feedback, int p_feedback_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start) { ERR_FAIL_COND(version); conditional_version.key=0; @@ -623,6 +642,8 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co attribute_pair_count=p_attribute_count; ubo_pairs=p_ubo_pairs; ubo_count=p_ubo_pair_count; + feedbacks=p_feedback; + feedback_count=p_feedback_count; //split vertex and shader code (thank you, retarded shader compiler programmers from you know what company). { diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index b9749b0228..8b402716a6 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -87,6 +87,12 @@ protected: int index; }; + struct Feedback { + + const char *name; + int conditional; + }; + bool uniforms_dirty; private: @@ -95,6 +101,7 @@ private: int texunit_pair_count; int conditional_count; int ubo_count; + int feedback_count; int vertex_code_start; int fragment_code_start; int attribute_pair_count; @@ -162,6 +169,7 @@ private: const AttributePair *attribute_pairs; const TexUnitPair *texunit_pairs; const UBOPair *ubo_pairs; + const Feedback *feedbacks; const char* vertex_code; const char* fragment_code; CharString fragment_code0; @@ -293,7 +301,7 @@ protected: _FORCE_INLINE_ int _get_uniform(int p_which) const; _FORCE_INLINE_ void _set_conditional(int p_which, bool p_value); - void setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start); + void setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs,int p_ubo_pair_count, const Feedback* p_feedback, int p_feedback_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start); ShaderGLES3(); public: diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 44d325b091..a9808dcbcf 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -7,4 +7,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('scene.glsl'); env.GLES3_GLSL('cubemap_filter.glsl'); env.GLES3_GLSL('cube_to_dp.glsl'); + env.GLES3_GLSL('blend_shape.glsl'); diff --git a/drivers/gles3/shaders/blend_shape.glsl b/drivers/gles3/shaders/blend_shape.glsl new file mode 100644 index 0000000000..4e0d066823 --- /dev/null +++ b/drivers/gles3/shaders/blend_shape.glsl @@ -0,0 +1,197 @@ +[vertex] + + +/* +from VisualServer: + +ARRAY_VERTEX=0, +ARRAY_NORMAL=1, +ARRAY_TANGENT=2, +ARRAY_COLOR=3, +ARRAY_TEX_UV=4, +ARRAY_TEX_UV2=5, +ARRAY_BONES=6, +ARRAY_WEIGHTS=7, +ARRAY_INDEX=8, +*/ + +#ifdef USE_2D_VERTEX +#define VFORMAT vec2 +#else +#define VFORMAT vec3 +#endif + +/* INPUT ATTRIBS */ + +layout(location=0) in highp VFORMAT vertex_attrib; +layout(location=1) in vec3 normal_attrib; + +#ifdef ENABLE_TANGENT +layout(location=2) in vec4 tangent_attrib; +#endif + +#ifdef ENABLE_COLOR +layout(location=3) in vec4 color_attrib; +#endif + +#ifdef ENABLE_UV +layout(location=4) in vec2 uv_attrib; +#endif + +#ifdef ENABLE_UV2 +layout(location=5) in vec2 uv2_attrib; +#endif + +#ifdef ENABLE_SKELETON +layout(location=6) in ivec4 bone_attrib; +layout(location=7) in vec4 weight_attrib; +#endif + +/* BLEND ATTRIBS */ + +#ifdef ENABLE_BLEND + +layout(location=8) in highp VFORMAT vertex_attrib_blend; +layout(location=9) in vec3 normal_attrib_blend; + +#ifdef ENABLE_TANGENT +layout(location=10) in vec4 tangent_attrib_blend; +#endif + +#ifdef ENABLE_COLOR +layout(location=11) in vec4 color_attrib_blend; +#endif + +#ifdef ENABLE_UV +layout(location=12) in vec2 uv_attrib_blend; +#endif + +#ifdef ENABLE_UV2 +layout(location=13) in vec2 uv2_attrib_blend; +#endif + +#ifdef ENABLE_SKELETON +layout(location=14) in ivec4 bone_attrib_blend; +layout(location=15) in vec4 weight_attrib_blend; +#endif + +#endif + +/* OUTPUTS */ + +out VFORMAT vertex_out; //tfb: + +#ifdef ENABLE_NORMAL +out vec3 normal_out; //tfb:ENABLE_NORMAL +#endif + +#ifdef ENABLE_TANGENT +out vec4 tangent_out; //tfb:ENABLE_TANGENT +#endif + +#ifdef ENABLE_COLOR +out vec4 color_out; //tfb:ENABLE_COLOR +#endif + +#ifdef ENABLE_UV +out vec2 uv_out; //tfb:ENABLE_UV +#endif + +#ifdef ENABLE_UV2 +out vec2 uv2_out; //tfb:ENABLE_UV2 +#endif + +#ifdef ENABLE_SKELETON +out ivec4 bone_out; //tfb:ENABLE_SKELETON +out vec4 weight_out; //tfb:ENABLE_SKELETON +#endif + +uniform float blend_amount; + +void main() { + + +#ifdef ENABLE_BLEND + + vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount; + +#ifdef ENABLE_NORMAL + normal_out = normal_attrib_blend + normal_attrib * blend_amount; +#endif + +#ifdef ENABLE_TANGENT + + tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount; + tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his +#endif + +#ifdef ENABLE_COLOR + + color_out = color_attrib_blend + color_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV + + uv_out = uv_attrib_blend + uv_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV2 + + uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount; +#endif + + +#ifdef ENABLE_SKELETON + + bone_out = bone_attrib_blend; + weight_out = weight_attrib_blend + weight_attrib * blend_amount; +#endif + +#else //ENABLE_BLEND + + + vertex_out = vertex_attrib * blend_amount; + +#ifdef ENABLE_NORMAL + normal_out = normal_attrib * blend_amount; +#endif + +#ifdef ENABLE_TANGENT + + tangent_out.xyz = tangent_attrib.xyz * blend_amount; + tangent_out.w = tangent_attrib.w; //just copy, no point in blending his +#endif + +#ifdef ENABLE_COLOR + + color_out = color_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV + + uv_out = uv_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV2 + + uv2_out = uv2_attrib * blend_amount; +#endif + + +#ifdef ENABLE_SKELETON + + bone_out = bone_attrib; + weight_out = weight_attrib * blend_amount; +#endif + +#endif + gl_Position = vec4(0.0); +} + +[fragment] + + +void main() { + +} + diff --git a/methods.py b/methods.py index f6bae4a64e..e1c8ef7d11 100755 --- a/methods.py +++ b/methods.py @@ -671,6 +671,7 @@ class LegacyGLHeaderStruct: self.fragment_lines=[] self.uniforms=[] self.attributes=[] + self.feedbacks=[] self.fbos=[] self.conditionals=[] self.enums={} @@ -823,6 +824,20 @@ def include_file_in_legacygl_header( filename, header_data, depth ): bind=bind.replace("attrib:","").strip() header_data.attributes+=[(name,bind)] + if ( line.strip().find("out ")==0 and line.find("tfb:")!=-1): + uline = line.replace("out ",""); + uline = uline.replace("highp ",""); + uline = uline.replace(";",""); + uline = uline[ uline.find(" "): ].strip() + + + if (uline.find("//")!=-1): + name,bind = uline.split("//") + if (bind.find("tfb:")!=-1): + name=name.strip() + bind=bind.replace("tfb:","").strip() + header_data.feedbacks+=[(name,bind)] + line=line.replace("\r","") line=line.replace("\n","") @@ -1039,12 +1054,14 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ): fd.write("\t\tstatic const Enum *_enums=NULL;\n") fd.write("\t\tstatic const EnumValue *_enum_values=NULL;\n") + conditionals_found = [] if (len(header_data.conditionals)): fd.write("\t\tstatic const char* _conditional_strings[]={\n") if (len(header_data.conditionals)): for x in header_data.conditionals: fd.write("\t\t\t\"#define "+x+"\\n\",\n"); + conditionals_found.append(x) fd.write("\t\t};\n\n"); else: fd.write("\t\tstatic const char **_conditional_strings=NULL;\n") @@ -1070,6 +1087,24 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ): else: fd.write("\t\tstatic AttributePair *_attribute_pairs=NULL;\n") + feedback_count=0 + + if (len(header_data.feedbacks)): + + fd.write("\t\tstatic const Feedback _feedbacks[]={\n") + for x in header_data.feedbacks: + name = x[0] + cond = x[1] + if (cond in conditionals_found): + fd.write("\t\t\t{\""+name+"\","+str(conditionals_found.index(cond))+"},\n"); + else: + fd.write("\t\t\t{\""+name+"\",-1},\n"); + + feedback_count+=1 + + fd.write("\t\t};\n\n"); + else: + fd.write("\t\tstatic const Feedback* _feedbacks=NULL;\n") if (len(header_data.texunits)): fd.write("\t\tstatic TexUnitPair _texunit_pairs[]={\n") @@ -1109,9 +1144,9 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ): fd.write("\t\tstatic const int _fragment_code_start="+str(header_data.fragment_offset)+";\n") if output_attribs: - fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_attribute_pairs,"+str(len(header_data.attributes))+", _texunit_pairs,"+str(len(header_data.texunits))+",_ubo_pairs,"+str(len(header_data.ubos))+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") + fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_attribute_pairs,"+str(len(header_data.attributes))+", _texunit_pairs,"+str(len(header_data.texunits))+",_ubo_pairs,"+str(len(header_data.ubos))+",_feedbacks,"+str(feedback_count)+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") else: - fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_texunit_pairs,"+str(len(header_data.texunits))+",_enums,"+str(len(header_data.enums))+",_enum_values,"+str(enum_value_count)+",_ubo_pairs,"+str(len(header_data.ubos))+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") + fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_texunit_pairs,"+str(len(header_data.texunits))+",_enums,"+str(len(header_data.enums))+",_enum_values,"+str(enum_value_count)+",_ubo_pairs,"+str(len(header_data.ubos))+",_feedbacks,"+str(feedback_count)+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") fd.write("\t};\n\n") diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index e737c5c37e..ec33bb53d9 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -316,14 +316,14 @@ void Mesh::add_surface(uint32_t p_format,PrimitiveType p_primitive,const DVector } -void Mesh::add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes) { +void Mesh::add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,uint32_t p_flags) { ERR_FAIL_COND(p_arrays.size()!=ARRAY_MAX); Surface s; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh,(VisualServer::PrimitiveType)p_primitive, p_arrays,p_blend_shapes); + VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh,(VisualServer::PrimitiveType)p_primitive, p_arrays,p_blend_shapes,p_flags); surfaces.push_back(s); @@ -1024,7 +1024,7 @@ void Mesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_morph_target_mode","mode"),&Mesh::set_morph_target_mode); ObjectTypeDB::bind_method(_MD("get_morph_target_mode"),&Mesh::get_morph_target_mode); - ObjectTypeDB::bind_method(_MD("add_surface_from_arrays","primitive","arrays","blend_shapes"),&Mesh::add_surface_from_arrays,DEFVAL(Array())); + ObjectTypeDB::bind_method(_MD("add_surface_from_arrays","primitive","arrays","blend_shapes","compress_flags"),&Mesh::add_surface_from_arrays,DEFVAL(Array()),DEFVAL(ARRAY_COMPRESS_DEFAULT)); ObjectTypeDB::bind_method(_MD("get_surface_count"),&Mesh::get_surface_count); ObjectTypeDB::bind_method(_MD("surface_remove","surf_idx"),&Mesh::surface_remove); ObjectTypeDB::bind_method(_MD("surface_get_array_len","surf_idx"),&Mesh::surface_get_array_len); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 2b28f1187e..b671d8c3b3 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -77,6 +77,22 @@ public: ARRAY_FORMAT_WEIGHTS=1<<ARRAY_WEIGHTS, ARRAY_FORMAT_INDEX=1<<ARRAY_INDEX, + ARRAY_COMPRESS_BASE=(ARRAY_INDEX+1), + ARRAY_COMPRESS_VERTEX=1<<(ARRAY_VERTEX+ARRAY_COMPRESS_BASE), // mandatory + ARRAY_COMPRESS_NORMAL=1<<(ARRAY_NORMAL+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TANGENT=1<<(ARRAY_TANGENT+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_COLOR=1<<(ARRAY_COLOR+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV=1<<(ARRAY_TEX_UV+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV2=1<<(ARRAY_TEX_UV2+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_BONES=1<<(ARRAY_BONES+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_WEIGHTS=1<<(ARRAY_WEIGHTS+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_INDEX=1<<(ARRAY_INDEX+ARRAY_COMPRESS_BASE), + + ARRAY_FLAG_USE_2D_VERTICES=ARRAY_COMPRESS_INDEX<<1, + ARRAY_FLAG_USE_16_BIT_BONES=ARRAY_COMPRESS_INDEX<<2, + + ARRAY_COMPRESS_DEFAULT=ARRAY_COMPRESS_VERTEX|ARRAY_COMPRESS_NORMAL|ARRAY_COMPRESS_TANGENT|ARRAY_COMPRESS_COLOR|ARRAY_COMPRESS_TEX_UV|ARRAY_COMPRESS_TEX_UV2|ARRAY_COMPRESS_WEIGHTS + }; enum PrimitiveType { @@ -122,7 +138,7 @@ protected: public: - void add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array()); + void add_surface_from_arrays(PrimitiveType p_primitive, const Array& p_arrays, const Array& p_blend_shapes=Array(), uint32_t p_flags=ARRAY_COMPRESS_DEFAULT); void add_surface(uint32_t p_format,PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >(),const Vector<AABB>& p_bone_aabbs=Vector<AABB>()); Array surface_get_arrays(int p_surface) const; diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 6f08d69221..8e6175fa5b 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -355,7 +355,30 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) { w=DVector<Color>::Write(); a[i]=array; } break; - case Mesh::ARRAY_FORMAT_BONES: + case Mesh::ARRAY_FORMAT_BONES: { + + + DVector<int> array; + array.resize(varr_len*4); + DVector<int>::Write w = array.write(); + + int idx=0; + for(List< Vertex >::Element *E=vertex_array.front();E;E=E->next(),idx+=4) { + + const Vertex &v=E->get(); + + ERR_CONTINUE( v.bones.size()!=4 ); + + for(int j=0;j<4;j++) { + w[idx+j]=v.bones[j]; + } + + } + + w=DVector<int>::Write(); + a[i]=array; + + } break; case Mesh::ARRAY_FORMAT_WEIGHTS: { @@ -367,18 +390,11 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) { for(List< Vertex >::Element *E=vertex_array.front();E;E=E->next(),idx+=4) { const Vertex &v=E->get(); + ERR_CONTINUE( v.weights.size()!=4 ); for(int j=0;j<4;j++) { - switch(i) { - case Mesh::ARRAY_WEIGHTS: { - ERR_CONTINUE( v.weights.size()!=4 ); - w[idx+j]=v.weights[j]; - } break; - case Mesh::ARRAY_BONES: { - ERR_CONTINUE( v.bones.size()!=4 ); - w[idx+j]=v.bones[j]; - } break; - } + + w[idx+j]=v.weights[j]; } } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 5f536b8fd4..21cf391af5 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -380,7 +380,8 @@ public: virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0; virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0; - + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 2439eacd75..0f7dabcc12 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -738,13 +738,25 @@ void VisualServerScene::instance_attach_object_instance_ID(RID p_instance,Object } void VisualServerScene::instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight){ + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_shape,instance->morph_values.size()); + instance->morph_values[p_shape]=p_weight; } + void VisualServerScene::instance_set_surface_material(RID p_instance,int p_surface, RID p_material){ Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND( !instance ); - _update_dirty_instance(instance); + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } ERR_FAIL_INDEX(p_surface,instance->materials.size()); @@ -770,13 +782,13 @@ void VisualServerScene::instance_attach_skeleton(RID p_instance,RID p_skeleton){ return; if (instance->skeleton.is_valid()) { - VSG::storage->instance_remove_dependency(p_skeleton,instance); + VSG::storage->instance_remove_skeleton(p_skeleton,instance); } instance->skeleton=p_skeleton; if (instance->skeleton.is_valid()) { - VSG::storage->instance_add_dependency(p_skeleton,instance); + VSG::storage->instance_add_skeleton(p_skeleton,instance); } _instance_queue_update(instance,true); @@ -2227,6 +2239,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) { if (p_instance->update_aabb) _update_instance_aabb(p_instance); + if (p_instance->update_materials) { if (p_instance->base_type==VS::INSTANCE_MESH) { @@ -2239,6 +2252,14 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) { } } p_instance->materials.resize(new_mat_count); + + int new_morph_count = VSG::storage->mesh_get_morph_target_count(p_instance->base); + if (new_morph_count!=p_instance->morph_values.size()) { + p_instance->morph_values.resize(new_morph_count); + for(int i=0;i<new_morph_count;i++) { + p_instance->morph_values[i]=0; + } + } } if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 27b08c4c50..ac894f1286 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -709,7 +709,7 @@ Error VisualServer::_surface_set_data(Array p_arrays,uint32_t p_format,uint32_t } break; case VS::ARRAY_BONES: { - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER ); DVector<int> array = p_arrays[ai]; @@ -912,7 +912,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi bsformat|=(1<<j); } - ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_BONES-1))); + ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_INDEX-1))); } } @@ -1089,7 +1089,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi DVector<uint8_t> noindex; AABB laabb; - Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array,array_len,noindex,0,laabb,bone_aabb); + Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array_shape,array_len,noindex,0,laabb,bone_aabb); aabb.merge_with(laabb); if (err) { ERR_EXPLAIN("Invalid blend shape array format for surface"); @@ -1194,9 +1194,9 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format,DVector<uint8_t> p case VS::ARRAY_BONES: { if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) { - elem_size=sizeof(uint32_t); - } else { elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(uint32_t); } } break; @@ -1487,7 +1487,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format,DVector<uint8_t> p DVector<int>::Write w = arr.write(); for(int j=0;j<p_vertex_len;j++) { - const int *v = (const int*)&r[j*total_elem_size+offsets[i]]; + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; for(int k=0;k<4;k++) { w[j*4+k]=v[k]; } diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp index fa9e372eb3..217a5fe78d 100644 --- a/tools/editor/io_plugins/editor_import_collada.cpp +++ b/tools/editor/io_plugins/editor_import_collada.cpp @@ -85,7 +85,7 @@ struct ColladaImport { Error _create_scene(Collada::Node *p_node, Spatial *p_parent); Error _create_resources(Collada::Node *p_node); Error _create_material(const String& p_material); - Error _create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes=Vector<Ref<Mesh> >()); + Error _create_mesh_surfaces(bool p_optimize, Ref<Mesh>& p_mesh, const Map<String,Collada::NodeGeometry::Material>& p_material_map, const Collada::MeshData &meshdata, const Transform& p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector<Ref<Mesh> > p_morph_meshes=Vector<Ref<Mesh> >(), bool p_for_morph=false); Error load(const String& p_path, int p_flags, bool p_force_make_tangents=false); void _fix_param_animation_tracks(); void create_animation(int p_clip,bool p_make_tracks_in_all_bones); @@ -597,7 +597,7 @@ static void _generate_tangents_and_binormals(const DVector<int>& p_indices,const } } -Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes) { +Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes,bool p_for_morph) { bool local_xform_mirror=p_local_xform.basis.determinant() < 0; @@ -1072,7 +1072,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con DVector<Color> final_color_array; DVector<Vector3> final_uv_array; DVector<Vector3> final_uv2_array; - DVector<float> final_bone_array; + DVector<int> final_bone_array; DVector<float> final_weight_array; uint32_t final_format=0; @@ -1223,12 +1223,12 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con if (has_weights) { DVector<float> weightarray; - DVector<float> bonearray; + DVector<int> bonearray; weightarray.resize(vertex_array.size()*4); DVector<float>::Write weightarrayw = weightarray.write(); bonearray.resize(vertex_array.size()*4); - DVector<float>::Write bonearrayw = bonearray.write(); + DVector<int>::Write bonearrayw = bonearray.write(); for(int k=0;k<vlen;k++) { float sum=0; @@ -1237,7 +1237,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con if (l<vertex_array[k].weights.size()) { weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=vertex_array[k].weights[l].weight; sum+=weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]; - bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=vertex_array[k].weights[l].bone_idx; + bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=int(vertex_array[k].weights[l].bone_idx); //COLLADA_PRINT(itos(k)+": "+rtos(bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l])+":"+rtos(weightarray[k*VS::ARRAY_WEIGHTS_SIZE+l])); } else { @@ -1254,7 +1254,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con } weightarrayw = DVector<float>::Write(); - bonearrayw = DVector<float>::Write(); + bonearrayw = DVector<int>::Write(); final_weight_array = weightarray; final_bone_array = bonearray; @@ -1461,14 +1461,20 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con // print_line("want surface "+itos(mi)+" has "+itos(p_morph_meshes[mi]->get_surface_count())); Array a = p_morph_meshes[mi]->surface_get_arrays(surface); - a[Mesh::ARRAY_BONES]=Variant(); - a[Mesh::ARRAY_WEIGHTS]=Variant(); + //add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not) + + if (final_weight_array.size()) + a[Mesh::ARRAY_WEIGHTS]=final_weight_array; + if (final_bone_array.size()) + a[Mesh::ARRAY_BONES]=final_bone_array; + a[Mesh::ARRAY_INDEX]=Variant(); //a.resize(Mesh::ARRAY_MAX); //no need for index mr.push_back(a); } - p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr); + + p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr,p_for_morph?0:Mesh::ARRAY_COMPRESS_DEFAULT); if (material.is_valid()) { p_mesh->surface_set_material(surface, material); @@ -1692,7 +1698,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { if (collada.state.mesh_data_map.has(meshid)) { Ref<Mesh> mesh=Ref<Mesh>(memnew( Mesh )); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; - Error err = _create_mesh_surfaces(false,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,NULL); + Error err = _create_mesh_surfaces(false,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,NULL,Vector<Ref<Mesh> >(),true); ERR_FAIL_COND_V(err,err); morphs.push_back(mesh); diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 3cd6d8336a..d650725e2e 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -1840,6 +1840,8 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) { void ScriptEditor::_help_class_open(const String& p_class) { + if (p_class=="") + return; for(int i=0;i<tab_container->get_child_count();i++) { |