Blend shapes using transform feedback (GPU)

This commit is contained in:
Juan Linietsky 2016-11-24 20:46:55 -03:00
parent 69c30709ec
commit a732708b9d
16 changed files with 726 additions and 162 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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