公司实现了自己的视频播放器,自己解码,生成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]; } }
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。