[engine] Spine 组件多纹理渲染支持 useTint

This commit is contained in:
SmallMain 2022-06-27 00:00:29 +08:00
parent d2a705be6d
commit f3c3a0eae8
4 changed files with 136 additions and 50 deletions

View File

@ -59,6 +59,16 @@ var vfmtPosUvTwoColor = new gfx.VertexFormat([
vfmtPosUvTwoColor.name = 'vfmtPosUvTwoColor'; vfmtPosUvTwoColor.name = 'vfmtPosUvTwoColor';
gfx.VertexFormat.XY_UV_Two_Color = vfmtPosUvTwoColor; gfx.VertexFormat.XY_UV_Two_Color = vfmtPosUvTwoColor;
var vfmtPosUvTwoColorTexId = new gfx.VertexFormat([
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
{ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
{ name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
{ name: gfx.ATTR_COLOR0, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
{ name: gfx.ATTR_TEX_ID, type: gfx.ATTR_TYPE_FLOAT32, num: 1 },
]);
vfmtPosUvTwoColorTexId.name = 'vfmtPosUvTwoColorTexId';
gfx.VertexFormat.XY_UV_Two_Color_TexId = vfmtPosUvTwoColorTexId;
var vfmtPosUv = new gfx.VertexFormat([ var vfmtPosUv = new gfx.VertexFormat([
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
{ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 } { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }
@ -86,5 +96,6 @@ module.exports = {
vfmtPosUv, vfmtPosUv,
vfmtPosColor, vfmtPosColor,
vfmtPos, vfmtPos,
vfmtPosUvColorTexId vfmtPosUvColorTexId,
vfmtPosUvTwoColorTexId,
}; };

View File

@ -480,11 +480,13 @@ sp.Skeleton = cc.Class({
// override base class _updateMaterial to set define value and clear material cache // override base class _updateMaterial to set define value and clear material cache
_updateMaterial () { _updateMaterial () {
let useTint = this.useTint || (this.isAnimationCached() && !CC_NATIVERENDERER); let useTint = this.useTint;
let baseMaterial = this.getMaterial(0); let baseMaterial = this.getMaterial(0);
if (baseMaterial) { if (baseMaterial) {
const isMultiSupport = baseMaterial.material.isMultiSupport(); const isMultiSupport = baseMaterial.material.isMultiSupport();
if (!isMultiSupport) { if (isMultiSupport) {
this._defineMaterialTint(baseMaterial, useTint);
} else {
baseMaterial.define('USE_TINT', useTint); baseMaterial.define('USE_TINT', useTint);
baseMaterial.define('CC_USE_MODEL', !this.enableBatch); baseMaterial.define('CC_USE_MODEL', !this.enableBatch);
} }
@ -501,7 +503,6 @@ sp.Skeleton = cc.Class({
); );
if (isMultiSupport) { if (isMultiSupport) {
if (this.useTint) this.useTint = false;
if (!this.enableBatch) this.enableBatch = true; if (!this.enableBatch) this.enableBatch = true;
} }
} }
@ -528,16 +529,25 @@ sp.Skeleton = cc.Class({
_updateUseTint () { _updateUseTint () {
let baseMaterial = this.getMaterial(0); let baseMaterial = this.getMaterial(0);
if (baseMaterial) { if (baseMaterial) {
let useTint = this.useTint || (this.isAnimationCached() && !CC_NATIVERENDERER); let useTint = this.useTint;
if (!baseMaterial.material.isMultiSupport()) { if (baseMaterial.material.isMultiSupport()) {
baseMaterial.define('USE_TINT', useTint); this._defineMaterialTint(baseMaterial, useTint);
} else { } else {
if (this.useTint) this.useTint = false; baseMaterial.define('USE_TINT', useTint);
} }
} }
this._materialCache = {}; this._materialCache = {};
}, },
_defineMaterialTint(material, useTint) {
const passes = material._effect._passes;
if (passes && passes.length > 0) {
if (passes[0]._defines['USE_TINT'] != useTint) {
material.define('USE_TINT', useTint);
}
}
},
// if change use batch mode, just clear material cache // if change use batch mode, just clear material cache
_updateBatch () { _updateBatch () {
let baseMaterial = this.getMaterial(0); let baseMaterial = this.getMaterial(0);

View File

@ -220,6 +220,7 @@ let AnimationCache = cc.Class({
colors : [], colors : [],
boneInfos : [], boneInfos : [],
vertices : null, vertices : null,
verticesMulti : null,
uintVert : null, uintVert : null,
indices : null, indices : null,
}; };

View File

@ -32,6 +32,7 @@ const VertexFormat = require('../../cocos2d/core/renderer/webgl/vertex-format')
const VFOneColor = VertexFormat.vfmtPosUvColor; const VFOneColor = VertexFormat.vfmtPosUvColor;
const VFOneColorTexId = VertexFormat.vfmtPosUvColorTexId; const VFOneColorTexId = VertexFormat.vfmtPosUvColorTexId;
const VFTwoColor = VertexFormat.vfmtPosUvTwoColor; const VFTwoColor = VertexFormat.vfmtPosUvTwoColor;
const VFTwoColorTexId = VertexFormat.vfmtPosUvTwoColorTexId;
const gfx = cc.gfx; const gfx = cc.gfx;
const FLAG_BATCH = 0x10; const FLAG_BATCH = 0x10;
@ -109,7 +110,7 @@ function _getSlotMaterial (tex, blendMode) {
if (!baseMaterial) return null; if (!baseMaterial) return null;
if (_useMulti) { if (_useMulti) {
let key = tex.getId() + src + dst; let key = tex.getId() + src + dst + _useTint;
let materialCache = _comp._materialCache; let materialCache = _comp._materialCache;
let materialInfo = materialCache[key]; let materialInfo = materialCache[key];
if (!materialInfo) { if (!materialInfo) {
@ -121,6 +122,8 @@ function _getSlotMaterial (tex, blendMode) {
materialInfo = { material: cc.MaterialVariant.create(baseMaterial), texId: texId }; materialInfo = { material: cc.MaterialVariant.create(baseMaterial), texId: texId };
} }
_comp._defineMaterialTint(baseMaterial, _useTint);
if (texId === -1) { if (texId === -1) {
materialInfo.material.setProperty('texture', tex); materialInfo.material.setProperty('texture', tex);
materialInfo.texId = 0; materialInfo.texId = 0;
@ -348,10 +351,12 @@ export default class SpineAssembler extends Assembler {
vbuf[v + 2] = _tempUv.x; // u vbuf[v + 2] = _tempUv.x; // u
vbuf[v + 3] = _tempUv.y; // v vbuf[v + 3] = _tempUv.y; // v
uintVData[v + 4] = _spineColorToInt32(_finalColor); // light color uintVData[v + 4] = _spineColorToInt32(_finalColor); // light color
if (_useMulti) {
vbuf[v + 5] = _texId; if (_useTint) {
uintVData[v + 5] = _spineColorToInt32(_darkColor);
if (_useMulti) vbuf[v + 6] = _texId;
} else { } else {
_useTint && (uintVData[v + 5] = _spineColorToInt32(_darkColor)); // dark color if (_useMulti) vbuf[v + 5] = _texId;
} }
} }
} else { } else {
@ -360,10 +365,12 @@ export default class SpineAssembler extends Assembler {
for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount; v < n; v += _perVertexSize) { for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount; v < n; v += _perVertexSize) {
uintVData[v + 4] = _finalColor32; // light color uintVData[v + 4] = _finalColor32; // light color
if (_useMulti) {
vbuf[v + 5] = _texId; if (_useTint) {
uintVData[v + 5] = _darkColor32;
if (_useMulti) vbuf[v + 6] = _texId;
} else { } else {
_useTint && (uintVData[v + 5] = _darkColor32); // dark color if (_useMulti) vbuf[v + 5] = _texId;
} }
} }
} }
@ -408,12 +415,12 @@ export default class SpineAssembler extends Assembler {
vbuf[offset + 2] = _tempUv.x; // u vbuf[offset + 2] = _tempUv.x; // u
vbuf[offset + 3] = _tempUv.y; // v vbuf[offset + 3] = _tempUv.y; // v
uintVData[offset + 4] = _spineColorToInt32(_finalColor); uintVData[offset + 4] = _spineColorToInt32(_finalColor);
if (_useMulti) {
vbuf[offset + 5] = _texId; if (_useTint) {
uintVData[offset + 5] = _spineColorToInt32(_darkColor);
if (_useMulti) vbuf[offset + 6] = _texId;
} else { } else {
if (_useTint) { if (_useMulti) vbuf[offset + 5] = _texId;
uintVData[offset + 5] = _spineColorToInt32(_darkColor);
}
} }
} }
} else { } else {
@ -425,13 +432,13 @@ export default class SpineAssembler extends Assembler {
_finalColor32 = ((clippedVertices[v + 5]<<24) >>> 0) + (clippedVertices[v + 4]<<16) + (clippedVertices[v + 3]<<8) + clippedVertices[v + 2]; _finalColor32 = ((clippedVertices[v + 5]<<24) >>> 0) + (clippedVertices[v + 4]<<16) + (clippedVertices[v + 3]<<8) + clippedVertices[v + 2];
uintVData[offset + 4] = _finalColor32; uintVData[offset + 4] = _finalColor32;
if (_useMulti) {
vbuf[offset + 5] = _texId; if (_useTint) {
_darkColor32 = ((clippedVertices[v + 11] << 24) >>> 0) + (clippedVertices[v + 10] << 16) + (clippedVertices[v + 9] << 8) + clippedVertices[v + 8];
uintVData[offset + 5] = _darkColor32;
if (_useMulti) vbuf[offset + 6] = _texId;
} else { } else {
if (_useTint) { if (_useMulti) vbuf[offset + 5] = _texId;
_darkColor32 = ((clippedVertices[v + 11] << 24) >>> 0) + (clippedVertices[v + 10] << 16) + (clippedVertices[v + 9] << 8) + clippedVertices[v + 8];
uintVData[offset + 5] = _darkColor32;
}
} }
} }
} }
@ -467,7 +474,7 @@ export default class SpineAssembler extends Assembler {
} }
// x y u v r1 g1 b1 a1 r2 g2 b2 a2 or x y u v r g b a // x y u v r1 g1 b1 a1 r2 g2 b2 a2 or x y u v r g b a
_perClipVertexSize = _useMulti ? 12 : (_useTint ? 12 : 8); _perClipVertexSize = _useTint ? (_useMulti ? 16 : 12) : (_useMulti ? 12 : 8);
_vertexFloatCount = 0; _vertexFloatCount = 0;
_vertexFloatOffset = 0; _vertexFloatOffset = 0;
@ -673,6 +680,22 @@ export default class SpineAssembler extends Assembler {
} }
} }
cacheVerticesConvertToMulti(vertices) {
const verticesMulti = new Float32Array(vertices.length + (vertices.length / 6));
for (let i = 0, j = 0; j < vertices.length;) {
verticesMulti[i++] = vertices[j++]; // x
verticesMulti[i++] = vertices[j++]; // y
verticesMulti[i++] = vertices[j++]; // u
verticesMulti[i++] = vertices[j++]; // v
verticesMulti[i++] = vertices[j++]; // color1
verticesMulti[i++] = vertices[j++]; // color2
verticesMulti[i++] = 0; // texId
}
return verticesMulti;
}
cacheTraverse (worldMat) { cacheTraverse (worldMat) {
let frame = _comp._curFrame; let frame = _comp._curFrame;
@ -687,6 +710,14 @@ export default class SpineAssembler extends Assembler {
let vertices = frame.vertices; let vertices = frame.vertices;
let indices = frame.indices; let indices = frame.indices;
let worldMatm; let worldMatm;
let useMultiTint = _useMulti && _useTint;
if (useMultiTint) {
if (!frame.verticesMulti) {
frame.verticesMulti = this.cacheVerticesConvertToMulti(frame.vertices);
}
vertices = frame.verticesMulti;
}
let frameVFOffset = 0, frameIndexOffset = 0, segVFCount = 0; let frameVFOffset = 0, frameIndexOffset = 0, segVFCount = 0;
if (worldMat) { if (worldMat) {
@ -706,7 +737,7 @@ export default class SpineAssembler extends Assembler {
let colorOffset = 0; let colorOffset = 0;
let colors = frame.colors; let colors = frame.colors;
let nowColor = colors[colorOffset++]; let nowColor = colors[colorOffset++];
let maxVFOffset = nowColor.vfOffset; let maxVFOffset = useMultiTint ? (nowColor.vfOffset + (nowColor.vfOffset / 6)) : nowColor.vfOffset;
_handleColor(nowColor); _handleColor(nowColor);
for (let i = 0, n = segments.length; i < n; i++) { for (let i = 0, n = segments.length; i < n; i++) {
@ -736,17 +767,17 @@ export default class SpineAssembler extends Assembler {
ibuf[ii] = _vertexOffset + indices[frameIndexOffset++]; ibuf[ii] = _vertexOffset + indices[frameIndexOffset++];
} }
segVFCount = segInfo.vfCount; segVFCount = useMultiTint ? (segInfo.vfCount + (segInfo.vfCount / 6)) : segInfo.vfCount;
vbuf.set(vertices.subarray(frameVFOffset, frameVFOffset + segVFCount), _vfOffset); vbuf.set(vertices.subarray(frameVFOffset, frameVFOffset + segVFCount), _vfOffset);
frameVFOffset += segVFCount; frameVFOffset += segVFCount;
if (calcTranslate) { if (calcTranslate) {
for (let ii = _vfOffset, il = _vfOffset + segVFCount; ii < il; ii += 6) { for (let ii = _vfOffset, il = _vfOffset + segVFCount; ii < il; ii += _perVertexSize) {
vbuf[ii] += _m12; vbuf[ii] += _m12;
vbuf[ii + 1] += _m13; vbuf[ii + 1] += _m13;
} }
} else if (needBatch) { } else if (needBatch) {
for (let ii = _vfOffset, il = _vfOffset + segVFCount; ii < il; ii += 6) { for (let ii = _vfOffset, il = _vfOffset + segVFCount; ii < il; ii += _perVertexSize) {
_x = vbuf[ii]; _x = vbuf[ii];
_y = vbuf[ii + 1]; _y = vbuf[ii + 1];
vbuf[ii] = _x * _m00 + _y * _m04 + _m12; vbuf[ii] = _x * _m00 + _y * _m04 + _m12;
@ -756,25 +787,58 @@ export default class SpineAssembler extends Assembler {
_buffer.adjustForSpine(_vertexCount, _indexCount); _buffer.adjustForSpine(_vertexCount, _indexCount);
if (_needColor) { // 使用多纹理材质,不使用 Tint 则用 TexId 在下标 5 覆盖 darkColor否则在 6 写入 TexId
// handle color // 不使用多纹理材质,则保持引擎默认的强制 Tint 不用做额外操作
let frameColorOffset = frameVFOffset - segVFCount;
for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += 6, frameColorOffset += 6) { if (_useMulti) {
if (frameColorOffset >= maxVFOffset) { if (_useTint) {
nowColor = colors[colorOffset++]; if (_needColor) {
_handleColor(nowColor); let frameColorOffset = frameVFOffset - segVFCount;
maxVFOffset = nowColor.vfOffset; for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += _perVertexSize, frameColorOffset += _perVertexSize) {
} if (frameColorOffset >= maxVFOffset) {
uintbuf[ii] = _finalColor32; nowColor = colors[colorOffset++];
if (_useMulti) { _handleColor(nowColor);
vbuf[ii + 1] = _texId; maxVFOffset = useMultiTint ? (nowColor.vfOffset + (nowColor.vfOffset / 6)) : nowColor.vfOffset;
}
uintbuf[ii] = _finalColor32;
uintbuf[ii + 1] = _darkColor32;
vbuf[ii + 2] = _texId;
}
} else { } else {
uintbuf[ii + 1] = _darkColor32; for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += _perVertexSize) {
vbuf[ii + 2] = _texId;
}
}
} else {
if (_needColor) {
let frameColorOffset = frameVFOffset - segVFCount;
for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += _perVertexSize, frameColorOffset += _perVertexSize) {
if (frameColorOffset >= maxVFOffset) {
nowColor = colors[colorOffset++];
_handleColor(nowColor);
maxVFOffset = useMultiTint ? (nowColor.vfOffset + (nowColor.vfOffset / 6)) : nowColor.vfOffset;
}
uintbuf[ii] = _finalColor32;
vbuf[ii + 1] = _texId;
}
} else {
for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += _perVertexSize) {
vbuf[ii + 1] = _texId;
}
} }
} }
} else if (_useMulti) { } else {
for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += 6) { if (_needColor) {
vbuf[ii + 1] = _texId; let frameColorOffset = frameVFOffset - segVFCount;
for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += _perVertexSize, frameColorOffset += _perVertexSize) {
if (frameColorOffset >= maxVFOffset) {
nowColor = colors[colorOffset++];
_handleColor(nowColor);
maxVFOffset = useMultiTint ? (nowColor.vfOffset + (nowColor.vfOffset / 6)) : nowColor.vfOffset;
}
uintbuf[ii] = _finalColor32;
uintbuf[ii + 1] = _darkColor32;
}
} }
} }
} }
@ -796,10 +860,10 @@ export default class SpineAssembler extends Assembler {
if (!baseMaterial) return; if (!baseMaterial) return;
_useMulti = baseMaterial.material.isMultiSupport(); _useMulti = baseMaterial.material.isMultiSupport();
_useTint = !_useMulti && (comp.useTint || comp.isAnimationCached()); _useTint = comp.useTint;
_vertexFormat = _useMulti ? VFOneColorTexId : (_useTint ? VFTwoColor : VFOneColor); _vertexFormat = _useTint ? (_useMulti ? VFTwoColorTexId : VFTwoColor) : (_useMulti ? VFOneColorTexId : (comp.isAnimationCached() ? VFTwoColor : VFOneColor));
// x y u v color1 color2 or x y u v color // x y u v color1 color2 or x y u v color
_perVertexSize = _useMulti ? 6 :(_useTint ? 6 : 5); _perVertexSize = _useTint ? (_useMulti ? 7 : 6) : (_useMulti ? 6 : (comp.isAnimationCached() ? 6 : 5));
_node = comp.node; _node = comp.node;
_buffer = renderer.getBuffer('mesh', _vertexFormat); _buffer = renderer.getBuffer('mesh', _vertexFormat);