-
Creator 版本: <3.6.0>
-
目标平台: <模拟器–>
-
重现方式:必现
渲染组件
渲染组件.zip (5.3 KB)
import {
IAssembler,
} from "cc";
import * as cc from "cc";
import {TextureAssembler} from "../Assemblers/TextureAssembler";
const {ccclass, property} = cc._decorator;
@ccclass
export default class TexturePlus extends cc.Sprite {
@property(cc.Vec2)
v1 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v2 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v3 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v4 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v5 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v6 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v8 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v9 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v10 : cc.Vec2 = cc.v2();
@property(cc.Vec2)
v11 : cc.Vec2 = cc.v2();
@property(cc.CCBoolean)
flipX : boolean = false;
v0 : cc.Vec2 = cc.v2();
v7 : cc.Vec2 = cc.v2(0,1);
indices: number[] = [];
uvList: cc.Vec2[] = [cc.v2(0,0),cc.v2(0.4,0),cc.v2(0.8,0),cc.v2(1,0),cc.v2(1,0.4),cc.v2(1,1),
cc.v2(0.4,1),cc.v2(0,1),cc.v2(0.2,0),cc.v2(0.6,0),cc.v2(1,0.6),cc.v2(0.7,1)];
uvList2: cc.Vec2[] = [];
protected onLoad() {
this.uvList2 = [this.v0,this.v1,this.v2,this.v3,this.v4,this.v5,this.v6,this.v7,this.v8,this.v9,this.v10,this.v11];
for(let i = 0;i < this.uvList2.length;++i){
this.uvList2[i].set(this.uvList[i]);
}
}
_assembler: IAssembler = null!;
protected _flushAssembler () {
// macro.UI_GPU_DRIVEN
const assembler = TextureAssembler;
if (this._assembler !== assembler) {
this.destroyRenderData();
this._assembler = assembler;
}
if (!this._renderData) {
this.updateRenderData();
}
}
public UpdateVerticies() {
this.indices.length = 0;
// Right bottom triangle
this.uvList2 = [this.v0,this.v1,this.v2,this.v3,this.v4,this.v5,this.v6,this.v7,this.v8,this.v9,this.v10,this.v11];
this.AddTriangle(2, this.v2, 4, this.v4, 3, this.v3);
// Left top triangle
this.AddTriangle(0, this.v0, 7, this.v7, 6, this.v6);
this.AddQuad(9, this.v9, 10, this.v10, 4, this.v4, 2, this.v2);
this.AddQuad(1, this.v1, 5, this.v5, 10, this.v10, 9, this.v9);
this.AddQuad(8, this.v8, 11, this.v11, 5, this.v5, 1, this.v1);
this.AddQuad(0, this.v0, 6, this.v6, 11, this.v11, 8, this.v8);
if(this._assembler && this.renderData){
this._assembler.updateVertexData(this);
}
}
protected lateUpdate(dt: number) {
this.UpdateVerticies();
}
private AddTriangle(textureIndex0: number, pos0: cc.Vec2, textureIndex1: number, pos1: cc.Vec2, textureIndex2: number, pos2: cc.Vec2) {
this.indices.push(textureIndex0);
if (!this.flipX) {
this.indices.push(textureIndex1);
this.indices.push(textureIndex2);
}
else {
this.indices.push(textureIndex2);
this.indices.push(textureIndex1);
}
}
private AddQuad(textureIndex0: number, pos0: cc.Vec2, textureIndex1: number, pos1: cc.Vec2, textureIndex2: number, pos2: cc.Vec2, textureIndex3: number, pos3: cc.Vec2) {
let v0 = textureIndex0;
let v1 = textureIndex1;
let v2 = textureIndex2;
let v3 = textureIndex3;
this.indices.push(v0);
if (!this.flipX) {
this.indices.push(v1);
this.indices.push(v2);
}
else {
this.indices.push(v2);
this.indices.push(v1);
}
this.indices.push(v0);
if (!this.flipX) {
this.indices.push(v2);
this.indices.push(v3);
}
else {
this.indices.push(v3);
this.indices.push(v2);
}
}
updateRenderData(){
this.UpdateVerticies();
if (this._assembler && this._assembler.createData) {
this._renderData = this._assembler.createData(this);
this._renderData!.material = this.customMaterial;
this.markForUpdateRenderData();
if (this.spriteFrame) {
this._assembler.updateUVs(this);
}
this._updateColor();
}
}
}
/*
Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import {dynamicAtlasManager, IAssembler, IRenderData, RenderData, sp, Sprite, Vec2, Vec3} from "cc";
import TexturePlus from "../Components/TexturePlus";
const vec3_temps: Vec3[] = [];
for (let i = 0; i < 4; i++) {
vec3_temps.push(new Vec3());
}
/**
* simple 组装器
* 可通过 `UI.simple` 获取该组装器。
*/
let floatsPerVert = 9;
export const TextureAssembler: IAssembler = {
createData(sprite: TexturePlus) {
const renderData = sprite.requestRenderData();
let points = sprite.uvList;
if (!points || points.length < 3) return;
renderData.dataLength = points.length;
let indicesCount = sprite.indices.length;
renderData.resize(points.length,indicesCount);
// @ts-ignore
renderData.chunk.setIndexBuffer(sprite.indices);
return renderData;
},
updateRenderData (sprite: Sprite) {
const frame = sprite.spriteFrame;
dynamicAtlasManager.packToDynamicAtlas(sprite, frame);
this.updateUVs(sprite);// dirty need
//this.updateColor(sprite);// dirty need
const renderData = sprite.renderData;
if (renderData && frame) {
if (renderData.vertDirty) {
this.updateVertexData(sprite);
}
renderData.updateRenderData(sprite, frame);
}
},
updateWorldVerts (sprite: Sprite, chunk: any) {
const renderData = sprite.renderData!;
const vData = chunk.vb;
const dataList: IRenderData[] = renderData.data;
const node = sprite.node;
const matrix = node.worldMatrix;
const stride = renderData.floatStride;
const vec3_temp = vec3_temps[0];
let offset = 0;
for (let i = 0; i < dataList.length; i++) {
const curData = dataList[i];
Vec3.set(vec3_temp, curData.x, curData.y, 0);
Vec3.transformMat4(vec3_temp, vec3_temp, matrix);
offset = i * stride;
vData[offset++] = vec3_temp.x;
vData[offset++] = vec3_temp.y;
vData[offset++] = vec3_temp.z;
}
},
fillBuffers(sprite: TexturePlus, renderer: any) {
if (sprite === null) {
return;
}
const renderData = sprite.renderData!;
const chunk = renderData.chunk;
if (sprite.node.hasChangedFlags || renderData.vertDirty) {
// const vb = chunk.vertexAccessor.getVertexBuffer(chunk.bufferId);
this.updateWorldVerts(sprite, chunk);
renderData.vertDirty = false;
}
const bid = chunk.bufferId;
const vidOrigin = chunk.vertexOffset;
// @ts-ignore
const meshBuffer = chunk.meshBuffer;
// @ts-ignore
const ib = chunk.meshBuffer.iData;
let indexOffset = meshBuffer.indexOffset;
let vid = vidOrigin;
const iData = sprite.indices;
for (let i = 0, l = iData.length; i < l; i++) {
ib[indexOffset++] = vid + iData[i];
}
meshBuffer.indexOffset += iData.length;
},
updateVertexData (sprite: TexturePlus) {
const renderData: RenderData | null = sprite.renderData;
if (!renderData) {
return;
}
const uiTrans = sprite.node._uiProps.uiTransformComp!;
const dataList: IRenderData[] = renderData.data;
const cw = uiTrans.width;
const ch = uiTrans.height;
const appX = uiTrans.anchorX * cw;
const appY = uiTrans.anchorY * ch;
let l = 0;
let b = 0;
let r = 0;
let t = 0;
if (sprite.trim) {
l = -appX;
b = -appY;
r = cw - appX;
t = ch - appY;
} else {
const frame = sprite.spriteFrame!;
const originSize = frame.originalSize;
const ow = originSize.width;
const oh = originSize.height;
const scaleX = cw / ow;
const scaleY = ch / oh;
// @ts-ignore
const trimmedBorder = frame.trimmedBorder;
l = trimmedBorder.x * scaleX - appX;
b = trimmedBorder.z * scaleY - appY;
r = cw + trimmedBorder.y * scaleX - appX;
t = ch + trimmedBorder.w * scaleY - appY;
}
let startX = l;
let startY = b;
let subX = r - l;
let subY = t - b;
for(let i = 0;i < sprite.uvList2.length;++i){
let pos = sprite.uvList2[i];
let x = sprite.flipX ? 1 - pos.x : pos.x;
dataList[i].x = x * subX + startX;
dataList[i].y = pos.y * subY + startY;
}
renderData.vertDirty = true;
},
updateUVs(sprite: TexturePlus) {
if (!sprite.spriteFrame) return;
const renderData = sprite.renderData!;
const vData = renderData.chunk.vb;
const uv = sprite.spriteFrame.uv;
let polygon = sprite.uvList;
let startX = uv[0];
let startY = uv[1];
let subX = uv[6] - startX;
let subY = uv[7] - startY;
let uvOffset = 3;
for (let i = 0; i < polygon.length; i++) {
let pos = polygon[i];
let rx = sprite.flipX ? 1 - pos.x : pos.x;
let dstOffset = floatsPerVert * i + uvOffset;
vData[dstOffset] = startX + rx * subX;
vData[dstOffset + 1] = startY + pos.y * subY;
}
},
updateColor(sprite: TexturePlus) {
const renderData = sprite.renderData!;
const vData = renderData.chunk.vb;
let colorOffset = 5;
const color = sprite.color;
const colorR = color.r / 255;
const colorG = color.g / 255;
const colorB = color.b / 255;
const colorA = sprite.node._uiProps.opacity;
for (let i = 0; i < sprite.uvList.length; i++,colorOffset += renderData.floatStride) {
vData![colorOffset] = colorR;
vData![colorOffset + 1] = colorG;
vData![colorOffset + 2] = colorB;
vData![colorOffset + 3] = colorA;
}
},
};
这部分也原生化了,目前不能这么定制 assembler,你定制的具体需求是什么可以说下
用材质定制就可以了吧,没理解为什么需要 assembler