Skip to content

Commit

Permalink
support unpack float32 texture to rgba8888 texture for skinning (#4473)
Browse files Browse the repository at this point in the history
* support unpack float32 texture to rgba8888 texture for skinning
  • Loading branch information
2youyou2 committed Jun 4, 2019
1 parent 51bdc40 commit c798f8f
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 45 deletions.
50 changes: 34 additions & 16 deletions cocos2d/core/3d/skeleton/CCSkinnedMeshRenderer.js
Expand Up @@ -31,6 +31,8 @@ const mat4 = cc.vmath.mat4;
let _m4_tmp = mat4.create();

const dummyNode = new cc.Node();
const JOINT_MATRICES_SIZE = 50;
const MAX_FLOAT_TEXTURE_SIZE = 64;

/**
* !#en
Expand All @@ -48,7 +50,7 @@ let SkinnedMeshRenderer = cc.Class({
},

ctor () {
this._jointsData = null;
this._jointsData = this._jointsFloat32Data = null;
this._jointsTexture = null;
this._joints = [];
},
Expand Down Expand Up @@ -180,9 +182,17 @@ let SkinnedMeshRenderer = cc.Class({
let jointCount = this._joints.length;
let customProperties = this._customProperties;

let ALLOW_FLOAT_TEXTURE = !!cc.sys.glExtension('OES_texture_float');
if (ALLOW_FLOAT_TEXTURE) {
// set jointsTexture
let inited = false;
if (jointCount <= JOINT_MATRICES_SIZE) {
inited = true;

this._jointsData = this._jointsFloat32Data = new Float32Array(jointCount * 16);
customProperties.setProperty('_jointMatrices', this._jointsFloat32Data);
customProperties.define('_USE_JOINTS_TEXTRUE', false);
}

let SUPPORT_FLOAT_TEXTURE = !!cc.sys.glExtension('OES_texture_float');
if (!inited) {
let size;
if (jointCount > 256) {
size = 64;
Expand All @@ -194,33 +204,41 @@ let SkinnedMeshRenderer = cc.Class({
size = 8;
}

this._jointsData = new Float32Array(size * size * 4);
this._jointsData = this._jointsFloat32Data = new Float32Array(size * size * 4);

let texture = this._jointsTexture || new cc.Texture2D();
texture.initWithData(this._jointsData, cc.Texture2D.PixelFormat.RGBA32F, size, size);
let pixelFormat = cc.Texture2D.PixelFormat.RGBA32F,
width = size,
height = size;

if (!SUPPORT_FLOAT_TEXTURE) {
this._jointsData = new Uint8Array(this._jointsFloat32Data.buffer);
pixelFormat = cc.Texture2D.PixelFormat.RGBA8888;
width *= 4;

cc.warn(`SkinnedMeshRenderer [${this.node.name}] has too much joints [${jointCount}] and device do not support float32 texture, fallback to use RGBA8888 texture, which is much slower.`);
}

let texture = this._jointsTexture || new cc.Texture2D();
texture.initWithData(this._jointsData, pixelFormat, width, height);
this._jointsTexture = texture;

customProperties.setProperty('_jointsTexture', texture.getImpl());
customProperties.setProperty('_jointsTextureSize', this._jointsTexture.width);
}
else {
this._jointsData = new Float32Array(jointCount * 16);
customProperties.define('_JOINT_MATRICES_SIZE', jointCount);
customProperties.setProperty('_jointMatrices', this._jointsData);
customProperties.setProperty('_jointsTextureSize', new Float32Array([width, height]));

customProperties.define('_JOINTS_TEXTURE_FLOAT32', SUPPORT_FLOAT_TEXTURE);
customProperties.define('_USE_JOINTS_TEXTRUE', true);
}

customProperties.define('_USE_SKINNING', true);
customProperties.define('_USE_JOINTS_TEXTRUE', ALLOW_FLOAT_TEXTURE);
},

_setJointsDataWithArray (iMatrix, matrixArray) {
let data = this._jointsData;
let data = this._jointsFloat32Data;
data.set(matrixArray, iMatrix * 16);
},

_setJointsDataWithMatrix (iMatrix, matrix) {
let data = this._jointsData;
let data = this._jointsFloat32Data;

data[16 * iMatrix + 0] = matrix.m00;
data[16 * iMatrix + 1] = matrix.m01;
Expand Down
107 changes: 78 additions & 29 deletions cocos2d/renderer/build/chunks/skinning.inc
Expand Up @@ -6,43 +6,92 @@
attribute vec4 a_joints;

#if _USE_JOINTS_TEXTRUE
uniform sampler2D _jointsTexture;
uniform float _jointsTextureSize;
uniform sampler2D _jointsTexture;
uniform vec2 _jointsTextureSize;

mat4 getBoneMatrix(const in float i) {
float size = _jointsTextureSize;
float j = i * 4.0;
float x = mod(j, size);
float y = floor(j / size);
#if _JOINTS_TEXTURE_FLOAT32
mat4 getBoneMatrix(const in float i) {
float width = _jointsTextureSize.x;
float height = _jointsTextureSize.y;
float j = i * 4.0;
float x = mod(j, width);
float y = floor(j / width);

float dx = 1.0 / size;
float dy = 1.0 / size;
float dx = 1.0 / width;
float dy = 1.0 / height;

y = dy * (y + 0.5);
y = dy * (y + 0.5);

vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y));
vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y));
vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y));
vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y));
vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y));
vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y));
vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y));
vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y));

return mat4(v1, v2, v3, v4);
}
return mat4(v1, v2, v3, v4);
}
#else
float decode32(vec4 rgba) {
float Sign = 1.0 - step(128.0, rgba[0]) * 2.0;
float Exponent = 2.0 * mod(rgba[0], 128.0) + step(128.0, rgba[1]) - 127.0;
float Mantissa = mod(rgba[1], 128.0) * 65536.0 + rgba[2] * 256.0 + rgba[3] + 8388608.0;
return Sign * exp2(Exponent - 23.0) * Mantissa;
}
vec4 decodevec4 (vec4 x, vec4 y, vec4 z, vec4 w) {
// TODO: check this on big endian devices
return vec4(
decode32(x.wzyx * 255.0),
decode32(y.wzyx * 255.0),
decode32(z.wzyx * 255.0),
decode32(w.wzyx * 255.0)
);
}

vec4 decodevec4 (float dx, float x, float y, float offset) {
return decodevec4(
texture2D(_jointsTexture, vec2(dx * (offset + 0.5), y)),
texture2D(_jointsTexture, vec2(dx * (offset + 1.5), y)),
texture2D(_jointsTexture, vec2(dx * (offset + 2.5), y)),
texture2D(_jointsTexture, vec2(dx * (offset + 3.5), y))
);
}

mat4 getBoneMatrix(const in float i) {
float width = _jointsTextureSize.x;
float height = _jointsTextureSize.y;
float j = i * 16.0;
float x = mod(j, width);
float y = floor(j / width);

float dx = 1.0 / width;
float dy = 1.0 / height;

y = dy * (y + 0.5);

vec4 v1 = decodevec4(dx, x, y, 0.0);
vec4 v2 = decodevec4(dx, x, y, 4.0);
vec4 v3 = decodevec4(dx, x, y, 8.0);
vec4 v4 = decodevec4(dx, x, y, 12.0);

return mat4(v1, v2, v3, v4);
}
#endif
#else
uniform mat4 _jointMatrices[_JOINT_MATRICES_SIZE];
const int _JOINT_MATRICES_SIZE = 50;
uniform mat4 _jointMatrices[_JOINT_MATRICES_SIZE];

mat4 getBoneMatrix(const in float i) {
return _jointMatrices[int(i)];
}
#endif
mat4 getBoneMatrix(const in float i) {
return _jointMatrices[int(i)];
}
#endif

mat4 skinMatrix() {
return
getBoneMatrix(a_joints.x) * a_weights.x +
getBoneMatrix(a_joints.y) * a_weights.y +
getBoneMatrix(a_joints.z) * a_weights.z +
getBoneMatrix(a_joints.w) * a_weights.w
;
}
mat4 skinMatrix() {
return
getBoneMatrix(a_joints.x) * a_weights.x +
getBoneMatrix(a_joints.y) * a_weights.y +
getBoneMatrix(a_joints.z) * a_weights.z +
getBoneMatrix(a_joints.w) * a_weights.w
;
}
#endif


Expand Down

0 comments on commit c798f8f

Please sign in to comment.