diff options
Diffstat (limited to 'drivers')
-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 |
7 files changed, 591 insertions, 124 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() { + +} + |