公司实现了自己的视频播放器,自己解码,生成Yuv422数据,然后用WebGL显示。
现在我们想要在pixi中渲染Yuv视频数据。
第一步,实现自己的render。参考:pixi自定义shader-BatchPluginFactory。
第二步,写一个自己的Sprite,重写_render方法。
PIXI中,BatchRender的渲染流程是:
start-render-flush
flush之前,可以调用多次render。
Sprite默认的_render:
_render(renderer)
{
this.calculateVertices();
renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
renderer.plugins[this.pluginName].render(this);
}重写之后:
_render(renderer) {
this.calculateVertices();
renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
for(let i = 0; i < this.textureArr.length; i++) {
this.texture = this.textureArr[i];
renderer.plugins[this.pluginName].render(this);
}
this.texture = this.textureArr[0];
}可以发现,我们调用了多次render。每次切换一个Texture,热农户调用render。因为没有调flush,所有的Texture都被上传了,存在了uniform sampler2D uSamplers[%count%]中。然后我们就可以在片段着色器中取纹理的像素,进行处理了。
完整代码:
(function(){
const fragment = `
varying vec2 vTextureCoord;
varying vec4 vColor;
varying float vTextureId;
uniform sampler2D uSamplers[%count%];
const mat4 YUV2RGB = mat4(
1.1643828125, 0, 1.59602734375, -.87078515625,
1.1643828125, -.39176171875, -.81296875, .52959375,
1.1643828125, 2.017234375, 0, -1.081390625,
0, 0, 0, 1
);
void main(void){
vec4 color;
%forloop%
highp float y = texture2D(uSamplers[0], vTextureCoord).r;
highp float u = texture2D(uSamplers[1], vTextureCoord).r;
highp float v = texture2D(uSamplers[2], vTextureCoord).r;
gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;
}
`;
const YuvBatchRenderer = PIXI.BatchPluginFactory.create({fragment});
PIXI.Renderer.registerPlugin('yuvBatch', YuvBatchRenderer);
})();
class YuvSprite extends PIXI.Sprite {
constructor(yData, cbData, crData, width, height){
super();
this.textureArr = [
PIXI.Texture.fromBuffer(yData, width, height, {format: PIXI.FORMATS.LUMINANCE}),
PIXI.Texture.fromBuffer(cbData, width / 2, height / 2, {format: PIXI.FORMATS.LUMINANCE}),
PIXI.Texture.fromBuffer(crData, width / 2, height / 2, {format: PIXI.FORMATS.LUMINANCE})
];
this.yData = yData;
this.cbData = cbData;
this.crData = crData;
this.pluginName = 'yuvBatch';
this.texture = this.textureArr[0];
}
destroy(options) {
super.destroy(options);
this.textureArr = null;
this.yData = null;
this.cbData = null;
this.crData = null;
}
setYuvData(yData, cbData, crData){
this.yData.set(yData);
this.cbData.set(cbData);
this.crData.set(crData);
this.textureArr.forEach((texture) => {
texture.update();
});
}
_render(renderer) {
this.calculateVertices();
renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
for(let i = 0; i < this.textureArr.length; i++) {
this.texture = this.textureArr[i];
renderer.plugins[this.pluginName].render(this);
}
this.texture = this.textureArr[0];
}
}
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。