Update: I got vertex coloring to work!
I wasn’t able to figure out how to reference the existing vfmtPosUvColor
in the engine, but just copying the definition and pasting it into my script worked. So this is now a self-contained custom Renderer that I think could be built off of for more complex things. I’d be interested in trying to minimize this code some more if possible, but it’s not too bad as it is.
// -----------------------------------------------------------------------------------------
// Component:
// -----------------------------------------------------------------------------------------
const RenderComponent = cc.RenderComponent;
const renderEngine = cc.renderer.renderEngine;
const SpriteMaterial = renderEngine.SpriteMaterial;
const gfx = renderEngine.gfx;
var vfmtPosUvColor = 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 },
]);
vfmtPosUvColor.name = 'vfmtPosUvColor';
let MyRenderer = cc.Class({
extends: RenderComponent,
properties: {
_texture: {
default: null,
type: cc.Texture2D,
},
texture: {
get: function () {
return this._texture;
},
set: function (value, force) {
this._texture = value;
this._activateMaterial();
},
type: cc.Texture2D,
},
},
ctor () {
},
onEnable: function () {
this._super();
this.node.setContentSize(100, 100);
this._activateMaterial();
},
_activateMaterial () {
let material = this._material;
if (!material) {
material = this._material = new SpriteMaterial();
material.useColor = false;
}
if (this._texture) {
material.texture = this._texture;
this.markForUpdateRenderData(true);
this.markForRender(true);
}
else {
this.disableRender();
}
this._updateMaterial(material);
},
});
// -----------------------------------------------------------------------------------------
// Assembler:
// -----------------------------------------------------------------------------------------
const RenderFlow = cc.RenderFlow;
const math = renderEngine.math;
const mat4 = math.mat4;
const vec3 = math.vec3;
let _mat4_temp = mat4.create();
let _vec3_temp = vec3.create();
MyRenderer._assembler = {
updateRenderData (comp) {
let renderData = comp._renderData;
if (!renderData) {
renderData = comp._renderData = comp.requestRenderData();
}
let size = comp.node._contentSize;
let anchor = comp.node._anchorPoint;
renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y);
renderData.material = comp.getMaterial();
this.updateVertices(comp);
},
fillBuffers (comp, renderer) {
let renderData = comp._renderData;
let data = renderData._data;
let buffer = renderer.getBuffer('mesh', vfmtPosUvColor),
vertexOffset = buffer.byteOffset >> 2,
vertexCount = renderData.vertexCount;
let indiceOffset = buffer.indiceOffset,
vertexId = buffer.vertexOffset;
buffer.request(vertexCount, renderData.indiceCount);
let vbuf = buffer._vData,
ibuf = buffer._iData,
uintbuf = buffer._uintVData;
for (let i = 0, l = renderData.vertexCount; i < l; i++) {
let vert = data[i];
vbuf[vertexOffset++] = vert.x;
vbuf[vertexOffset++] = vert.y;
vbuf[vertexOffset++] = vert.u;
vbuf[vertexOffset++] = vert.v;
uintbuf[vertexOffset++] = vert.color;
}
for (let i = 0, l = renderData.indiceCount; i < l; i+=6) {
ibuf[indiceOffset++] = vertexId;
ibuf[indiceOffset++] = vertexId+1;
ibuf[indiceOffset++] = vertexId+2;
ibuf[indiceOffset++] = vertexId+1;
ibuf[indiceOffset++] = vertexId+3;
ibuf[indiceOffset++] = vertexId+2;
vertexId += 4;
}
comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA;
},
updateVertices (comp) {
let node = comp.node;
let renderData = comp._renderData;
let data = renderData._data;
renderData.dataLength = renderData.vertexCount = renderData.indiceCount = 0;
let appx = node._anchorPoint.x * node._contentSize.width,
appy = node._anchorPoint.y * node._contentSize.height;
mat4.copy(_mat4_temp, node._worldMatrix);
vec3.set(_vec3_temp, -appx, -appy, 0);
mat4.translate(_mat4_temp, _mat4_temp, _vec3_temp);
let a = _mat4_temp.m00, b = _mat4_temp.m01, c = _mat4_temp.m04, d = _mat4_temp.m05,
tx = _mat4_temp.m12, ty = _mat4_temp.m13;
let dataOffset = 0;
renderData.vertexCount += 4;
renderData.indiceCount += 6;
renderData.dataLength = renderData.vertexCount;
let grid = {
l: 0,
r: 1,
t: 1,
b: 0,
}
let colors = {
tl: cc.Color.RED._val,
tr: cc.Color.GREEN._val,
bl: cc.Color.BLUE._val,
br: cc.Color.YELLOW._val,
}
let left = 0;
let top = 0;
let right = node._contentSize.width;
let bottom = node._contentSize.height;
// tl
data[dataOffset].x = left * a + top * c + tx;
data[dataOffset].y = left * b + top * d + ty;
data[dataOffset].u = grid.l;
data[dataOffset].v = grid.t;
data[dataOffset].color = colors.tl;
dataOffset++;
// bl
data[dataOffset].x = left * a + bottom * c + tx;
data[dataOffset].y = left * b + bottom * d + ty;
data[dataOffset].u = grid.l;
data[dataOffset].v = grid.b;
data[dataOffset].color = colors.bl;
dataOffset++;
// tr
data[dataOffset].x = right * a + top * c + tx;
data[dataOffset].y = right * b + top * d + ty;
data[dataOffset].u = grid.r;
data[dataOffset].v = grid.t;
data[dataOffset].color = colors.tr;
dataOffset++;
// br
data[dataOffset].x = right * a + bottom * c + tx;
data[dataOffset].y = right * b + bottom * d + ty;
data[dataOffset].u = grid.r;
data[dataOffset].v = grid.b;
data[dataOffset].color = colors.br;
dataOffset++;
},
};
module.exports = MyRenderer;
Sample: