Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support unpack float32 texture to rgba8888 texture for skinning #4473

Merged
merged 2 commits into from
Jun 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 34 additions & 16 deletions cocos2d/core/3d/skeleton/CCSkinnedMeshRenderer.js
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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