Jump to content

Batch RenderTexture.render()?


omnivibe
 Share

Recommended Posts

Actually, I might just abandon Phaser and DIY with Pixi... seems like this community is far more active...

 

By "put everything you need to render on a single DisplayObjectContainer", how can I do that with a single image?

 

In my use case I have a single image which is a brush. I want to draw that brush around on the screen, i.e. by blitting it many times across a path. What would be the best way to do this?

Link to comment
Share on other sites

Here is how I ended up doing it with Pixi, following what you said... is this the fastest way? I guess I'm most concerned about needing to create the sprite and tint it each time... or is that an extremely fast operation?

 

drawLine() will actually be called very often, to draw continuous lines/curves as the user drags their mouse across the screen

var stage;var renderer;var currentBrushName = 'myBrushName';var currentBrushColor = 0xFF0000;var drawLayer;var drawLayerContainer;var lastPosition = null;var isDrawing = false;function setupPIXI() {stage = new PIXI.Stage(0xffffff);renderer = PIXI.autoDetectRenderer(800,600);$("#game").append(renderer.view);drawLayer = new PIXI.RenderTexture(800, 600);drawLayerContainer = new PIXI.Sprite(drawLayer);stage.addChild(drawLayerContainer);}function mainGameLoop() {requestAnimFrame(mainGameLoop);renderer.render(stage);}function tintBrush() {currentBrushColor = parseInt("0x" + $("#brushColor").val(), 16);}function loadAssets() {function onAssetsLoaded() {drawLine(getLine(10,10,500,500));requestAnimFrame(mainGameLoop);}var loader = new PIXI.AssetLoader(['assets/images/atlas/brushes.json']);loader.onComplete = onAssetsLoaded;loader.load();}function getBrushSprite(point) {var spr = PIXI.Sprite.fromFrame(currentBrushName);spr.tint = currentBrushColor;spr.x = point.x;spr.y = point.y;return(spr);}function drawLine(line) {var spr;var idx;var point;var drawBuffer = new PIXI.DisplayObjectContainer();for (idx = 0; idx < line.length; idx++) {point = line[idx];spr = getBrushSprite(point);drawBuffer.addChild(spr);}drawLayer.render(drawBuffer);}$(document).ready(function () {setupPIXI();tintBrush();$("#brushColor").change(tintBrush);loadAssets();});//This will get a collection of PIXI.Points() along the coordinatesfunction getLine(x1, y1, x2, y2) {}
Link to comment
Share on other sites

Actually, I might just abandon Phaser and DIY with Pixi... seems like this community is far more active...

For painting app PIXI(or just canvas) would be better imho.

 

Yeah, that should be fast enough. Possible optimization -  reuse sprites(use object pool) and the DisplayObjectContainer instead re-creating them.

Link to comment
Share on other sites

OK, here is my updated code. Did some housekeeping too :)

 

Any more ways to optimize?

 

It's used like just the following, after preloading a spritesheet that contains myBrushName

 

Used like:

drawLayer = new DrawLayer(800,600);drawLayer.initBrush('myBrushName',0xFF0000);stage.addChild(drawLayer);...//when brush is changed call drawLayer.initBrush() again

Here's the main code for DrawLayer:

DrawLayer.prototype = new PIXI.DisplayObjectContainer();DrawLayer.prototype.constructor = DrawLayer;var BrushMode = {    NONE: "none",    DRAW: "draw",    ERASE: "erase"}/*    Brush Pool*/function BrushPool(_brushName, _brushColor) {    this.brushName = _brushName;    this.brushColor = _brushColor;    this.sprites = [];    this.grow(10);}BrushPool.prototype.grow = function(num) {    var idx;    var spr;    for(idx = 0; idx < num; idx++) {        spr = PIXI.Sprite.fromFrame(this.brushName);        spr.tint = this.brushColor;        spr.anchor.x = .5;        spr.anchor.y = .5;        this.sprites.push(spr);    }}BrushPool.prototype.growTo = function(num) {    var diff = num - this.sprites.length;    if(diff > 0) {        console.log("Growing by " + diff)        this.grow(diff);    }}BrushPool.prototype.getBrush = function(idx, point) {    var spr = this.sprites[idx];    spr.x = point.x;    spr.y = point.y;    return(spr);}/*    Draw Layer*/function DrawLayer(width, height) {    PIXI.DisplayObjectContainer.call(this);    this.interactive = true;    this.renderTexture = new PIXI.RenderTexture(800, 600);    this.spriteContainer = new PIXI.Sprite(this.renderTexture);    this.displayBuffer = new PIXI.DisplayObjectContainer();    this.brushPool = null;    this.brushMode = BrushMode.DRAW;    this.isDrawing = false;    this.lastMousePoint = new PIXI.Point(0,0);    this.addChild(this.spriteContainer);    this.mousedown = this.touchstart = function(data) {        if(this.brushMode != BrushMode.NONE) {            this.isDrawing = true;            this.lastMousePoint.x = data.getLocalPosition(this.parent).x;            this.lastMousePoint.y = data.getLocalPosition(this.parent).y;            this.drawPoints([this.lastMousePoint]);        }    };    this.mouseup = this.mouseupoutside = this.touchend = this.touchendoutside = function(data) {        this.isDrawing = false;    };    this.mousemove = this.touchmove = function(data)    {        if(this.isDrawing)        {            var nextMousePoint = data.getLocalPosition(this.parent);            this.drawPoints(this.getLine(this.lastMousePoint.x, this.lastMousePoint.y, nextMousePoint.x, nextMousePoint.y));            this.lastMousePoint = nextMousePoint;        }    };}DrawLayer.prototype.initBrush = function(brushName, brushColor) {    this.brushPool = new BrushPool(brushName, brushColor);}DrawLayer.prototype.drawPoints = function(points) {    var spr;    var idx;    if(this.displayBuffer.children.length) {        this.displayBuffer.removeChildren(0, this.displayBuffer.children.length);    }    this.brushPool.growTo(points.length);    for (idx = 0; idx < points.length; idx++) {        spr = this.brushPool.getBrush(idx, points[idx]);        this.displayBuffer.addChild(spr);    }    this.renderTexture.render(this.displayBuffer);}DrawLayer.prototype.getLine = function(x1, y1, x2, y2) {    var line = [];//Adds an array of points from x1,y1 to x2,y2 to line//...    return (line);}
Link to comment
Share on other sites

Yeah I need to tint the sprites. Seems to work really well... though when I tried replacing the native PIXI touch with HammerJS, the placement of the sprites got all weird...

 

i.e. spr.anchor.x = .5;

 

needs to become spr.anchor.x = 1; on Desktop and spr.anchor.x = 2 on iPad. Any idea why that is and how to automate it to be right?

Link to comment
Share on other sites

HammerJS gives you the position relative to window, are you converting it to local(relative to canvas element) position?

You can use this function to convert the position:

 

 

    function globalToLocalPosition(globalPosition, element) {        var offset = getOffset(element);        return {            x: globalPosition.x - offset.left,            y: globalPosition.y - offset.top        };    }     function getOffset(el) {        var _x = 0;        var _y = 0;        while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {            _x += el.offsetLeft - el.scrollLeft;            _y += el.offsetTop - el.scrollTop;            el = el.offsetParent;        }        return { left: _x, top: _y};    }
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...