summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp11
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp401
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h72
-rw-r--r--drivers/gles3/shader_gles3.cpp23
-rw-r--r--drivers/gles3/shader_gles3.h10
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/blend_shape.glsl197
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() {
+
+}
+