You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-12 13:20:55 +00:00
Skeletons are now working.
This commit is contained in:
@@ -626,7 +626,12 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
|
|||||||
}
|
}
|
||||||
|
|
||||||
id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
|
id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
|
||||||
|
} else if (e->instance->base_type == VS::INSTANCE_MESH) {
|
||||||
|
if (e->instance->skeleton.is_valid()) {
|
||||||
|
id.flags |= INSTANCE_DATA_FLAG_SKELETON;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//forward
|
//forward
|
||||||
|
|
||||||
uint32_t reflection_count = 0;
|
uint32_t reflection_count = 0;
|
||||||
@@ -746,6 +751,9 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
|
|||||||
switch (e->instance->base_type) {
|
switch (e->instance->base_type) {
|
||||||
case VS::INSTANCE_MESH: {
|
case VS::INSTANCE_MESH: {
|
||||||
primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index);
|
primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index);
|
||||||
|
if (e->instance->skeleton.is_valid()) {
|
||||||
|
xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, 1);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case VS::INSTANCE_MULTIMESH: {
|
case VS::INSTANCE_MULTIMESH: {
|
||||||
RID mesh = storage->multimesh_get_mesh(e->instance->base);
|
RID mesh = storage->multimesh_get_mesh(e->instance->base);
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
|
|||||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
|
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
|
||||||
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16,
|
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16,
|
||||||
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7,
|
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7,
|
||||||
|
INSTANCE_DATA_FLAG_SKELETON = 1 << 19,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InstanceData {
|
struct InstanceData {
|
||||||
|
|||||||
@@ -2010,11 +2010,104 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
|||||||
return mesh->custom_aabb;
|
return mesh->custom_aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_skeleton.is_valid()) {
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
|
||||||
|
if (!skeleton || skeleton->size == 0) {
|
||||||
return mesh->aabb;
|
return mesh->aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh->aabb;
|
AABB aabb;
|
||||||
|
|
||||||
|
for (int i = 0; i < mesh->surface_count; i++) {
|
||||||
|
|
||||||
|
AABB laabb;
|
||||||
|
if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
|
||||||
|
|
||||||
|
int bs = mesh->surfaces[i]->bone_aabbs.size();
|
||||||
|
const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
|
||||||
|
|
||||||
|
int sbs = skeleton->size;
|
||||||
|
ERR_CONTINUE(bs > sbs);
|
||||||
|
const float *baseptr = skeleton->data.ptr();
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
if (skeleton->use_2d) {
|
||||||
|
for (int j = 0; j < bs; j++) {
|
||||||
|
|
||||||
|
if (skbones[0].size == Vector3())
|
||||||
|
continue; //bone is unused
|
||||||
|
|
||||||
|
const float *dataptr = baseptr + j * 8;
|
||||||
|
|
||||||
|
Transform mtx;
|
||||||
|
|
||||||
|
mtx.basis.elements[0].x = dataptr[0];
|
||||||
|
mtx.basis.elements[1].x = dataptr[1];
|
||||||
|
mtx.origin.x = dataptr[3];
|
||||||
|
|
||||||
|
mtx.basis.elements[0].y = dataptr[4];
|
||||||
|
mtx.basis.elements[1].y = dataptr[5];
|
||||||
|
mtx.origin.y = dataptr[7];
|
||||||
|
|
||||||
|
AABB baabb = mtx.xform(skbones[j]);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
laabb = baabb;
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
laabb.merge_with(baabb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int j = 0; j < bs; j++) {
|
||||||
|
|
||||||
|
if (skbones[0].size == Vector3())
|
||||||
|
continue; //bone is unused
|
||||||
|
|
||||||
|
const float *dataptr = baseptr + j * 12;
|
||||||
|
|
||||||
|
Transform mtx;
|
||||||
|
|
||||||
|
mtx.basis.elements[0][0] = dataptr[0];
|
||||||
|
mtx.basis.elements[0][1] = dataptr[1];
|
||||||
|
mtx.basis.elements[0][2] = dataptr[2];
|
||||||
|
mtx.origin.x = dataptr[3];
|
||||||
|
mtx.basis.elements[1][0] = dataptr[4];
|
||||||
|
mtx.basis.elements[1][1] = dataptr[5];
|
||||||
|
mtx.basis.elements[1][2] = dataptr[6];
|
||||||
|
mtx.origin.y = dataptr[7];
|
||||||
|
mtx.basis.elements[2][0] = dataptr[8];
|
||||||
|
mtx.basis.elements[2][1] = dataptr[9];
|
||||||
|
mtx.basis.elements[2][2] = dataptr[10];
|
||||||
|
mtx.origin.z = dataptr[11];
|
||||||
|
|
||||||
|
AABB baabb = mtx.xform(skbones[j]);
|
||||||
|
if (first) {
|
||||||
|
laabb = baabb;
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
laabb.merge_with(baabb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (laabb.size == Vector3()) {
|
||||||
|
laabb = mesh->surfaces[i]->aabb;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
laabb = mesh->surfaces[i]->aabb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
aabb = laabb;
|
||||||
|
} else {
|
||||||
|
aabb.merge_with(laabb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageRD::mesh_clear(RID p_mesh) {
|
void RasterizerStorageRD::mesh_clear(RID p_mesh) {
|
||||||
@@ -2783,6 +2876,186 @@ void RasterizerStorageRD::_update_dirty_multimeshes() {
|
|||||||
multimesh_dirty_list = nullptr;
|
multimesh_dirty_list = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SKELETON */
|
||||||
|
|
||||||
|
/* SKELETON API */
|
||||||
|
|
||||||
|
RID RasterizerStorageRD::skeleton_create() {
|
||||||
|
|
||||||
|
return skeleton_owner.make_rid(Skeleton());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
|
||||||
|
|
||||||
|
if (!skeleton->dirty) {
|
||||||
|
skeleton->dirty = true;
|
||||||
|
skeleton->dirty_list = skeleton_dirty_list;
|
||||||
|
skeleton_dirty_list = skeleton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
ERR_FAIL_COND(!skeleton);
|
||||||
|
ERR_FAIL_COND(p_bones < 0);
|
||||||
|
|
||||||
|
if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton)
|
||||||
|
return;
|
||||||
|
|
||||||
|
skeleton->size = p_bones;
|
||||||
|
skeleton->use_2d = p_2d_skeleton;
|
||||||
|
skeleton->uniform_set_3d = RID();
|
||||||
|
|
||||||
|
if (skeleton->buffer.is_valid()) {
|
||||||
|
RD::get_singleton()->free(skeleton->buffer);
|
||||||
|
skeleton->buffer = RID();
|
||||||
|
skeleton->data.resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skeleton->size) {
|
||||||
|
|
||||||
|
skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
|
||||||
|
skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
|
||||||
|
zeromem(skeleton->data.ptrw(), skeleton->data.size() * sizeof(float));
|
||||||
|
|
||||||
|
_skeleton_make_dirty(skeleton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
ERR_FAIL_COND_V(!skeleton, 0);
|
||||||
|
|
||||||
|
return skeleton->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!skeleton);
|
||||||
|
ERR_FAIL_INDEX(p_bone, skeleton->size);
|
||||||
|
ERR_FAIL_COND(skeleton->use_2d);
|
||||||
|
|
||||||
|
float *dataptr = skeleton->data.ptrw() + p_bone * 12;
|
||||||
|
|
||||||
|
dataptr[0] = p_transform.basis.elements[0][0];
|
||||||
|
dataptr[1] = p_transform.basis.elements[0][1];
|
||||||
|
dataptr[2] = p_transform.basis.elements[0][2];
|
||||||
|
dataptr[3] = p_transform.origin.x;
|
||||||
|
dataptr[4] = p_transform.basis.elements[1][0];
|
||||||
|
dataptr[5] = p_transform.basis.elements[1][1];
|
||||||
|
dataptr[6] = p_transform.basis.elements[1][2];
|
||||||
|
dataptr[7] = p_transform.origin.y;
|
||||||
|
dataptr[8] = p_transform.basis.elements[2][0];
|
||||||
|
dataptr[9] = p_transform.basis.elements[2][1];
|
||||||
|
dataptr[10] = p_transform.basis.elements[2][2];
|
||||||
|
dataptr[11] = p_transform.origin.z;
|
||||||
|
|
||||||
|
_skeleton_make_dirty(skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!skeleton, Transform());
|
||||||
|
ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform());
|
||||||
|
ERR_FAIL_COND_V(skeleton->use_2d, Transform());
|
||||||
|
|
||||||
|
const float *dataptr = skeleton->data.ptr() + p_bone * 12;
|
||||||
|
|
||||||
|
Transform t;
|
||||||
|
|
||||||
|
t.basis.elements[0][0] = dataptr[0];
|
||||||
|
t.basis.elements[0][1] = dataptr[1];
|
||||||
|
t.basis.elements[0][2] = dataptr[2];
|
||||||
|
t.origin.x = dataptr[3];
|
||||||
|
t.basis.elements[1][0] = dataptr[4];
|
||||||
|
t.basis.elements[1][1] = dataptr[5];
|
||||||
|
t.basis.elements[1][2] = dataptr[6];
|
||||||
|
t.origin.y = dataptr[7];
|
||||||
|
t.basis.elements[2][0] = dataptr[8];
|
||||||
|
t.basis.elements[2][1] = dataptr[9];
|
||||||
|
t.basis.elements[2][2] = dataptr[10];
|
||||||
|
t.origin.z = dataptr[11];
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!skeleton);
|
||||||
|
ERR_FAIL_INDEX(p_bone, skeleton->size);
|
||||||
|
ERR_FAIL_COND(!skeleton->use_2d);
|
||||||
|
|
||||||
|
float *dataptr = skeleton->data.ptrw() + p_bone * 8;
|
||||||
|
|
||||||
|
dataptr[0] = p_transform.elements[0][0];
|
||||||
|
dataptr[1] = p_transform.elements[1][0];
|
||||||
|
dataptr[2] = 0;
|
||||||
|
dataptr[3] = p_transform.elements[2][0];
|
||||||
|
dataptr[4] = p_transform.elements[0][1];
|
||||||
|
dataptr[5] = p_transform.elements[1][1];
|
||||||
|
dataptr[6] = 0;
|
||||||
|
dataptr[7] = p_transform.elements[2][1];
|
||||||
|
|
||||||
|
_skeleton_make_dirty(skeleton);
|
||||||
|
}
|
||||||
|
Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!skeleton, Transform2D());
|
||||||
|
ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
|
||||||
|
ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
|
||||||
|
|
||||||
|
const float *dataptr = skeleton->data.ptr() + p_bone * 8;
|
||||||
|
|
||||||
|
Transform2D t;
|
||||||
|
t.elements[0][0] = dataptr[0];
|
||||||
|
t.elements[1][0] = dataptr[1];
|
||||||
|
t.elements[2][0] = dataptr[3];
|
||||||
|
t.elements[0][1] = dataptr[4];
|
||||||
|
t.elements[1][1] = dataptr[5];
|
||||||
|
t.elements[2][1] = dataptr[7];
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!skeleton->use_2d);
|
||||||
|
|
||||||
|
skeleton->base_transform_2d = p_base_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::_update_dirty_skeletons() {
|
||||||
|
|
||||||
|
while (skeleton_dirty_list) {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_dirty_list;
|
||||||
|
|
||||||
|
if (skeleton->size) {
|
||||||
|
|
||||||
|
RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton_dirty_list = skeleton->dirty_list;
|
||||||
|
|
||||||
|
skeleton->instance_dependency.instance_notify_changed(true, false);
|
||||||
|
|
||||||
|
skeleton->dirty = false;
|
||||||
|
skeleton->dirty_list = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton_dirty_list = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* LIGHT */
|
/* LIGHT */
|
||||||
|
|
||||||
RID RasterizerStorageRD::light_create(VS::LightType p_type) {
|
RID RasterizerStorageRD::light_create(VS::LightType p_type) {
|
||||||
@@ -3601,6 +3874,14 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageRD::skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
|
||||||
|
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
ERR_FAIL_COND(!skeleton);
|
||||||
|
|
||||||
|
p_instance->update_dependency(&skeleton->instance_dependency);
|
||||||
|
}
|
||||||
|
|
||||||
VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
|
VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
|
||||||
|
|
||||||
if (mesh_owner.owns(p_rid)) {
|
if (mesh_owner.owns(p_rid)) {
|
||||||
@@ -3621,6 +3902,7 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
|
|||||||
void RasterizerStorageRD::update_dirty_resources() {
|
void RasterizerStorageRD::update_dirty_resources() {
|
||||||
_update_queued_materials();
|
_update_queued_materials();
|
||||||
_update_dirty_multimeshes();
|
_update_dirty_multimeshes();
|
||||||
|
_update_dirty_skeletons();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
|
bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
|
||||||
@@ -3705,6 +3987,12 @@ bool RasterizerStorageRD::free(RID p_rid) {
|
|||||||
MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
|
MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
|
||||||
multimesh->instance_dependency.instance_notify_deleted(p_rid);
|
multimesh->instance_dependency.instance_notify_deleted(p_rid);
|
||||||
multimesh_owner.free(p_rid);
|
multimesh_owner.free(p_rid);
|
||||||
|
} else if (skeleton_owner.owns(p_rid)) {
|
||||||
|
_update_dirty_skeletons();
|
||||||
|
skeleton_allocate(p_rid, 0);
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_rid);
|
||||||
|
skeleton->instance_dependency.instance_notify_deleted(p_rid);
|
||||||
|
skeleton_owner.free(p_rid);
|
||||||
} else if (reflection_probe_owner.owns(p_rid)) {
|
} else if (reflection_probe_owner.owns(p_rid)) {
|
||||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
|
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
|
||||||
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
|
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
|
||||||
|
|||||||
@@ -327,6 +327,32 @@ private:
|
|||||||
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
|
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
|
||||||
_FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
|
_FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
|
||||||
void _update_dirty_multimeshes();
|
void _update_dirty_multimeshes();
|
||||||
|
|
||||||
|
/* Skeleton */
|
||||||
|
|
||||||
|
struct Skeleton {
|
||||||
|
bool use_2d = false;
|
||||||
|
int size = 0;
|
||||||
|
Vector<float> data;
|
||||||
|
RID buffer;
|
||||||
|
|
||||||
|
bool dirty = false;
|
||||||
|
Skeleton *dirty_list = nullptr;
|
||||||
|
Transform2D base_transform_2d;
|
||||||
|
|
||||||
|
RID uniform_set_3d;
|
||||||
|
|
||||||
|
RasterizerScene::InstanceDependency instance_dependency;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable RID_Owner<Skeleton> skeleton_owner;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
|
||||||
|
|
||||||
|
Skeleton *skeleton_dirty_list = nullptr;
|
||||||
|
|
||||||
|
void _update_dirty_skeletons();
|
||||||
|
|
||||||
/* LIGHT */
|
/* LIGHT */
|
||||||
|
|
||||||
struct Light {
|
struct Light {
|
||||||
@@ -740,16 +766,33 @@ public:
|
|||||||
|
|
||||||
/* SKELETON API */
|
/* SKELETON API */
|
||||||
|
|
||||||
RID skeleton_create() { return RID(); }
|
RID skeleton_create();
|
||||||
void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) {}
|
void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
|
||||||
void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {}
|
void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
|
||||||
void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) {}
|
void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform);
|
||||||
int skeleton_get_bone_count(RID p_skeleton) const { return 0; }
|
int skeleton_get_bone_count(RID p_skeleton) const;
|
||||||
void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) {}
|
void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform);
|
||||||
Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { return Transform(); }
|
Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
|
||||||
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {}
|
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
|
||||||
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { return Transform2D(); }
|
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
|
||||||
|
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||||
|
if (skeleton->use_2d) {
|
||||||
|
return RID();
|
||||||
|
}
|
||||||
|
if (!skeleton->uniform_set_3d.is_valid()) {
|
||||||
|
Vector<RD::Uniform> uniforms;
|
||||||
|
RD::Uniform u;
|
||||||
|
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||||
|
u.binding = 0;
|
||||||
|
u.ids.push_back(skeleton->buffer);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
return skeleton->uniform_set_3d;
|
||||||
|
}
|
||||||
/* Light API */
|
/* Light API */
|
||||||
|
|
||||||
RID light_create(VS::LightType p_type);
|
RID light_create(VS::LightType p_type);
|
||||||
@@ -873,7 +916,7 @@ public:
|
|||||||
float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const;
|
float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const;
|
||||||
|
|
||||||
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
|
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
|
||||||
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}
|
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
|
||||||
|
|
||||||
/* GI PROBE API */
|
/* GI PROBE API */
|
||||||
|
|
||||||
|
|||||||
@@ -136,13 +136,35 @@ void main() {
|
|||||||
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
||||||
vec3 tangent = tangent_attrib.xyz;
|
vec3 tangent = tangent_attrib.xyz;
|
||||||
float binormalf = tangent_attrib.a;
|
float binormalf = tangent_attrib.a;
|
||||||
|
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) {
|
||||||
|
//multimesh, instances are for it
|
||||||
|
|
||||||
|
uvec2 bones_01 = uvec2(bone_attrib.x&0xFFFF,bone_attrib.x>>16) * 3;
|
||||||
|
uvec2 bones_23 = uvec2(bone_attrib.y&0xFFFF,bone_attrib.y>>16) * 3;
|
||||||
|
vec2 weights_01 = unpackUnorm2x16(bone_attrib.z);
|
||||||
|
vec2 weights_23 = unpackUnorm2x16(bone_attrib.w);
|
||||||
|
|
||||||
|
mat4 m = mat4(transforms.data[bones_01.x],transforms.data[bones_01.x+1],transforms.data[bones_01.x+2],vec4(0.0,0.0,0.0,1.0)) * weights_01.x;
|
||||||
|
m += mat4(transforms.data[bones_01.y],transforms.data[bones_01.y+1],transforms.data[bones_01.y+2],vec4(0.0,0.0,0.0,1.0)) * weights_01.y;
|
||||||
|
m += mat4(transforms.data[bones_23.x],transforms.data[bones_23.x+1],transforms.data[bones_23.x+2],vec4(0.0,0.0,0.0,1.0)) * weights_23.x;
|
||||||
|
m += mat4(transforms.data[bones_23.y],transforms.data[bones_23.y+1],transforms.data[bones_23.y+2],vec4(0.0,0.0,0.0,1.0)) * weights_23.y;
|
||||||
|
|
||||||
|
//reverse order because its transposed
|
||||||
|
vertex = (vec4(vertex,1.0) * m).xyz;
|
||||||
|
normal = (vec4(normal,0.0) * m).xyz;
|
||||||
|
|
||||||
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
||||||
|
|
||||||
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
|
tangent = (vec4(tangent,0.0) * m).xyz;
|
||||||
|
binormal = (vec4(binormal,0.0) * m).xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(UV_USED)
|
#if defined(UV_USED)
|
||||||
uv_interp = uv_attrib;
|
uv_interp = uv_attrib;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ layout(set=0,binding=8,std140) uniform SceneData {
|
|||||||
//3 bits of stride
|
//3 bits of stride
|
||||||
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
|
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
|
||||||
|
|
||||||
|
#define INSTANCE_FLAGS_SKELETON (1 << 19)
|
||||||
|
|
||||||
|
|
||||||
struct InstanceData {
|
struct InstanceData {
|
||||||
|
|||||||
Reference in New Issue
Block a user