最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to draw transparent trails using PIXI.js? - Stack Overflow

programmeradmin2浏览0评论

I've started playing with PIXI.js and tried to port this basic actionscript 3 snippet:

import flash.display.Sprite;
import flash.events.Event;

var trails:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00000000);//create a transparent bitmap to draw the trails into
var trailsFade:ColorTransform = new ColorTransform(1,1,1,0.25,0,0,0,1);//color transform: keep rgb the same(1,1,1), set alpha to 0.025 out of 1.0
var background:Bitmap = addChild(new Bitmap(trails,PixelSnapping.AUTO,true)) as Bitmap;//add the trails pixels/bitmap data into a Bitmap/display object at the bottom of the display list

var dot:Sprite = addChild(new Sprite()) as Sprite;
dot.graphics.lineStyle(3);
dot.graphics.drawCircle(-4, -4, 8);

addEventListener(Event.ENTER_FRAME,update);
function update(e:Event):void{
    dot.x = mouseX;
    dot.y = mouseY;
    //draw trails of the dot
    trails.draw(dot,dot.transform.concatenatedMatrix,trailsFade);//draw the dot into the bitmap data using the dot's transformation (x,y, rotation, scale)
}

What it does is draws a circle and takes a snapshot of it into a BitmapData object and there is a ColorMatrix filter applied with a small alpha/transparency value.

I've noticed PIXI.js has a lot of similarities and there is a ColorMatrixFilter available, but I couldn't figure out what the equivalent of BitmapData.draw() is in PIXI.js. The closest thing I found is the RenderTexture demo

Based on that I've tried to port the as3 code above:

var renderer = PIXI.autoDetectRenderer(640, 480);
	document.body.appendChild(renderer.view);

	var stage = new PIXI.Container();
	
	var dot = new PIXI.Graphics();
	dot.beginFill(0xFF9900);
	dot.drawCircle(-8,-8,16);
	dot.endFill();
	stage.addChild(dot);

	var renderTexture = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
	var renderTexture2 = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
	var currentTexture = renderTexture;

	var outputSprite = new PIXI.Sprite(currentTexture);
	stage.addChild(outputSprite);


	animate();

	function animate() {
		var a = Date.now() * 0.001;
		dot.x = renderer.width * 0.5 + (Math.cos(a) * 200);
		dot.y = renderer.height * 0.5 + (Math.sin(a) * 200);

		// swap the buffers ...
	    var temp = renderTexture;
	    renderTexture = renderTexture2;
	    renderTexture2 = temp;

	    renderTexture2.render(stage, null, false);

	    renderer.render(stage);
	    requestAnimationFrame( animate );
	}
<script src=".js/3.0.11/pixi.min.js"></script>

I've started playing with PIXI.js and tried to port this basic actionscript 3 snippet:

import flash.display.Sprite;
import flash.events.Event;

var trails:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00000000);//create a transparent bitmap to draw the trails into
var trailsFade:ColorTransform = new ColorTransform(1,1,1,0.25,0,0,0,1);//color transform: keep rgb the same(1,1,1), set alpha to 0.025 out of 1.0
var background:Bitmap = addChild(new Bitmap(trails,PixelSnapping.AUTO,true)) as Bitmap;//add the trails pixels/bitmap data into a Bitmap/display object at the bottom of the display list

var dot:Sprite = addChild(new Sprite()) as Sprite;
dot.graphics.lineStyle(3);
dot.graphics.drawCircle(-4, -4, 8);

addEventListener(Event.ENTER_FRAME,update);
function update(e:Event):void{
    dot.x = mouseX;
    dot.y = mouseY;
    //draw trails of the dot
    trails.draw(dot,dot.transform.concatenatedMatrix,trailsFade);//draw the dot into the bitmap data using the dot's transformation (x,y, rotation, scale)
}

What it does is draws a circle and takes a snapshot of it into a BitmapData object and there is a ColorMatrix filter applied with a small alpha/transparency value.

I've noticed PIXI.js has a lot of similarities and there is a ColorMatrixFilter available, but I couldn't figure out what the equivalent of BitmapData.draw() is in PIXI.js. The closest thing I found is the RenderTexture demo

Based on that I've tried to port the as3 code above:

var renderer = PIXI.autoDetectRenderer(640, 480);
	document.body.appendChild(renderer.view);

	var stage = new PIXI.Container();
	
	var dot = new PIXI.Graphics();
	dot.beginFill(0xFF9900);
	dot.drawCircle(-8,-8,16);
	dot.endFill();
	stage.addChild(dot);

	var renderTexture = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
	var renderTexture2 = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
	var currentTexture = renderTexture;

	var outputSprite = new PIXI.Sprite(currentTexture);
	stage.addChild(outputSprite);


	animate();

	function animate() {
		var a = Date.now() * 0.001;
		dot.x = renderer.width * 0.5 + (Math.cos(a) * 200);
		dot.y = renderer.height * 0.5 + (Math.sin(a) * 200);

		// swap the buffers ...
	    var temp = renderTexture;
	    renderTexture = renderTexture2;
	    renderTexture2 = temp;

	    renderTexture2.render(stage, null, false);

	    renderer.render(stage);
	    requestAnimationFrame( animate );
	}
<script src="https://cdnjs.cloudflare./ajax/libs/pixi.js/3.0.11/pixi.min.js"></script>

If you run the code snippet, you'll notice the circle leaves trails, which is good. However I'd like to control the transparency of these trails. How can that this be achieved ?

What's the best way to draw transparent trails using PIXI.js ?

(Additionally, I get this warning in console:

[.CommandBufferContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: Source 

and destination textures of the draw are the same.

How can this be remedied ?)

Update

To Illustrate, here's the same idea using p5.js:

function setup() {
  createCanvas(400,300);
  noStroke();
}

function draw() {
  //transparent rectangle
  fill(0,10);
  rect(0,0,width,height);
  //shape that will leave trails because buffer isn't cleared pletely
  fill(255);
  ellipse(mouseX,mouseY,30,30);
}
<script src="https://cdnjs.cloudflare./ajax/libs/p5.js/0.5.0/p5.min.js"></script>

I thought I could achieve this with a ColorMatrixFilter, but I couldn't find an exhaustive documentation (as it's arguments are different from the as3 ColorMatrixFilter). I will try with a GLSL shader as a CustomFilter next. What's the equivalent using PIXI.js ? Ideally something that will be efficient and scale well (allowing easy trails for thousands of objects)?

Share Improve this question edited May 27, 2016 at 22:11 George Profenza asked May 25, 2016 at 14:00 George ProfenzaGeorge Profenza 51.9k20 gold badges154 silver badges222 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

Looking at your p5 example, you can achieve the same result with PIXI using a single Graphics object. Not sure how well this will work with thousands of objects, but I wouldn't imagine the p5 one to perform any better since it does the same thing.

var renderer = PIXI.autoDetectRenderer(640, 480);
document.body.appendChild(renderer.view);

var stage = new PIXI.Container();
	
var graphics = new PIXI.Graphics();
stage.addChild(graphics);

animate();

function animate() {
	var a = Date.now() * 0.001;

	var x = renderer.width * 0.5 + (Math.cos(a) * 200);
   	var y = renderer.height * 0.5 + (Math.sin(a) * 200);

        //Draw a circle
	graphics.beginFill(0xFF9900);
	graphics.drawCircle(x-8, y-8, 16);
	graphics.endFill();

        //Draw background
	graphics.beginFill(0, 0.1);
	graphics.drawRect(0, 0, renderer.width, renderer.height);
	graphics.endFill();

  	renderer.render(stage);
	requestAnimationFrame( animate );
}
<script src="https://cdnjs.cloudflare./ajax/libs/pixi.js/3.0.11/pixi.min.js"></script>


Another approach is to bine this with the example using the RenderTextures. This may run faster with 1000 objects.

var renderer = PIXI.autoDetectRenderer(640, 480);
document.body.appendChild(renderer.view);

var stage = new PIXI.Container();

var renderTexture = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
var renderTexture2 = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
var outputSprite = new PIXI.Sprite(renderTexture);
stage.addChild(outputSprite);

var dot = new PIXI.Graphics();
dot.beginFill(0xFF9900);
dot.drawCircle(-8,-8,16);
dot.endFill();
dot.cacheAsBitmap = true;
stage.addChild(dot);

var bg = new PIXI.Graphics();
bg.beginFill(0, 0.1);
bg.drawRect(0, 0, renderer.width, renderer.height);
bg.endFill();
bg.cacheAsBitmap = true;
stage.addChild(bg);

animate();
function animate() {
    requestAnimationFrame( animate );

    var a = Date.now() * 0.001;
    dot.x = renderer.width * 0.5 + (Math.cos(a) * 200);
    dot.y = renderer.height * 0.5 + (Math.sin(a) * 200);

    // swap the buffers ...
    var temp = renderTexture;
    renderTexture = renderTexture2;
    renderTexture2 = temp;
    outputSprite.texture = renderTexture;

    renderTexture2.render(stage, null, false);
    renderer.render(stage);
}
<script src="https://cdnjs.cloudflare./ajax/libs/pixi.js/3.0.11/pixi.min.js"></script>

The PIXI.Graphics object has an "alpha" attribute. Your dots can be transparent by adding

dot.alpha = 0.25; // this is the value in the as3 script you shared

Here's how it looks like:

var renderer = PIXI.autoDetectRenderer(640, 480);
	document.body.appendChild(renderer.view);

	var stage = new PIXI.Container();
	
	var dot = new PIXI.Graphics();
	dot.beginFill(0xFF9900);
	dot.drawCircle(-8,-8,16);
	dot.endFill();
	stage.addChild(dot);

	var renderTexture = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
	var renderTexture2 = new PIXI.RenderTexture(renderer, renderer.width, renderer.height);
	var currentTexture = renderTexture;

	var outputSprite = new PIXI.Sprite(currentTexture);
	stage.addChild(outputSprite);


	animate();

	function animate() {
		var a = Date.now() * 0.001;
		dot.x = renderer.width * 0.5 + (Math.cos(a) * 200);
		dot.y = renderer.height * 0.5 + (Math.sin(a) * 200);
		dot.alpha = 0.25;
		// swap the buffers ...
	    var temp = renderTexture;
	    renderTexture = renderTexture2;
	    renderTexture2 = temp;

	    renderTexture2.render(stage, null, false);

	    renderer.render(stage);
	    requestAnimationFrame( animate );
	}
<script src="https://cdnjs.cloudflare./ajax/libs/pixi.js/3.0.11/pixi.min.js"></script>

发布评论

评论列表(0)

  1. 暂无评论