color的val
this._val = ((a << 24) >>> 0) + (b << 16) + (g << 8) + (r|0);
使用4字节整数表示rgba, 从低位到高位依次是rgba
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 }, ]);
为啥看到了蓝色
const red = new cc.Color(255, 0, 0, 255); red._val = 4278190335 // 白色 4294967295 vbuf[index]=red._val
4278190335 使用float32Array存储,4字节刚好是01
00
7F
4F
, 对应的颜色刚好是#01007F4F
,这个颜色刚好是带有透明度的暗蓝色,这也解释了为啥我看到的是蓝色
所以颜色是不能这么设置的。
createData (index, verticesFloats, indicesCount) { let vertices = new Float32Array(verticesFloats);// 注意这里是Float32Array let indices = new Uint16Array(indicesCount); this.updateMesh(index, vertices, indices); }, updateMesh (index, vertices:Float32Array, indices) { // 指向的都是同一个vertices this.vDatas[index] = vertices; this.uintVDatas[index] = new Uint32Array(vertices.buffer, 0, vertices.length); // 但是这个使用的是Uint32Array //这个类型非常重要,如果还是Float32Array,会导致存储的数据异常,因为整数和浮点数的存储方式是不同的 // 所以看到这里转接了一层,这样方便再updateColor中设置4字节整数的时候正常 this.iDatas[index] = indices; this.meshCount = this.vDatas.length; }, // assembler-2d updateColor (comp, color) { let uintVerts:Uint32Array = this._renderData.uintVDatas[0]; if (!uintVerts) return; color = color != null ? color : comp.node.color._val; let floatsPerVert = this.floatsPerVert; let colorOffset = this.colorOffset; for (let i = colorOffset, l = uintVerts.length; i < l; i += floatsPerVert) { uintVerts[i] = color; } }
engine
每个meshbuffer都有对应的vertexformat,决定了这个buffer的数据如何解析填充到gpu
function _commitTextures(gl, cur, next) { for (let i = 0; i < next.maxTextureSlot + 1; ++i) { if (cur.textureUnits[i] !== next.textureUnits[i]) { let texture = next.textureUnits[i];// 取纹理 if (texture && texture._glID !== -1) { gl.activeTexture(gl.TEXTURE0 + i); gl.bindTexture(texture._target, texture._glID); } } } }
textureUnits
是通过外部设置的
setTexture(name, texture, slot) { if (slot >= this._caps.maxTextureUnits) { console.warn(`Can not set texture ${name} at stage ${slot}, max texture exceed: ${this._caps.maxTextureUnits}`); return; } this._next.textureUnits[slot] = texture;// 这里设置新的纹理 this.setUniform(name, slot); if (this._next.maxTextureSlot < slot) { this._next.maxTextureSlot = slot; } }
往上溯源,发现
_setProperty (prop) { // 省略了好多的代码 device.setTexture(prop.name, param, this._allocTextureUnit()); }
又见到了熟悉的_draw
函数
_draw (item) { // for each pass for (let i = 0; i < passes.length; ++i) { let program = programLib.getProgram(pass, defines, effect.name); device.setProgram(program); let uniforms = program._uniforms;// 对应effect里面对应的所有uniform变量 let variants = pass._properties; // 对应effect里面的pass定义的properties for (let j = 0; j < uniforms.length; j++) { let prop = variants[uniforms[j].name]; if (prop !== undefined){ this._setProperty(prop); } } } }
builtin-2d-sprite.mtl
{ "__type__": "cc.Material", "_name": "builtin-2d-sprite", "_objFlags": 0, "_native": "", "_effectAsset": { "__uuid__": "2874f8dd-416c-4440-81b7-555975426e93" }, "_techniqueData": { "0": { "defines": { "USE_TEXTURE": true } } } }
builtin-2d-sprite.effect
CCEffect %{ techniques: - passes: - vert: vs frag: fs blendState: targets: - blend: true rasterizerState: cullMode: none properties: texture: { value: white } alphaThreshold: { value: 0.5 } }% CCProgram vs %{ precision highp float; #include <cc-global> #include <cc-local> in vec3 a_position; in vec4 a_color; out vec4 v_color; #if USE_TEXTURE in vec2 a_uv0; out vec2 v_uv0; #endif void main () { vec4 pos = vec4(a_position, 1); #if CC_USE_MODEL pos = cc_matViewProj * cc_matWorld * pos; #else pos = cc_matViewProj * pos; #endif #if USE_TEXTURE v_uv0 = a_uv0; #endif v_color = a_color; gl_Position = pos; } }% CCProgram fs %{ precision highp float; #include <alpha-test> #include <texture> in vec4 v_color; #if USE_TEXTURE in vec2 v_uv0; uniform sampler2D texture; #endif void main () { vec4 o = vec4(1, 1, 1, 1); #if USE_TEXTURE CCTexture(texture, v_uv0, o); #endif o *= v_color; ALPHA_TEST(o); #if USE_BGRA gl_FragColor = o.bgra; #else gl_FragColor = o.rgba; #endif } }%