Jump to content

Bizarre lineStyle Behavior


NickXitco
 Share

Recommended Posts

Hello! 

I'm new to this forum but I had a burning question that I can't seem to solve and was hoping to get some sort of help.

I'm trying to write a function to animate a bezier curve that changes styles (color and weight). I'm splitting up the curve into many straight line segments so that I can apply a style to each line segment to get an illusion of a gradient. I'm doing this by using two graphics objects (A and B), where A that animates the "head" or leading segment of the bezier curve (the one that's moving), and B renders the lasting tail segments that I want to persist after the animation is done.

For reference, here is the drawing line segments code. lineStyle is not applied anywhere else in the codebase.

    static drawSegments(graphics, camera, segments, startIndex) {
        for (let i = startIndex; i < segments.length; i++) {
            const segment = segments[i];
            //Prevents edges from appearing too thin.
            //Increasing threshold will make small lines larger, vice versa.
            const THRESHOLD = 0.5;
            const strokeWeight = Math.max(segment.u.weight, THRESHOLD / camera.getZoomFactor().x);
            const color = ColorUtilities.hsv2rgb(segment.u.hue, segment.u.sat, 100);
            const hexColor = ColorUtilities.rgb2hex(color.r, color.g, color.b);
            const randomColor = Math.random() * 0xFFFFFF;

            console.log(color);
            graphics.lineStyle({
                width: strokeWeight,
                color: hexColor,
                cap: PIXI.LINE_CAP.ROUND,
            });
            graphics.moveTo(segment.u.x, segment.u.y);
            graphics.lineTo(segment.v.x, segment.v.y);
        }
    }

If I clear B every frame (B.clear();), the lineStyle behaves correctly, as you can see in the first photo below, the line smooths from a small indigo line to a larger pink-ish one. However, this isn't great for me performance wise, as I want to have many of these lines, and drawing them from scratch every frame is expensive. Therefore I'm trying to just draw the segments that B hasn't already drawn yet. So every frame B will draw more and more lines. However, if I do it this way I get a strange result.

image.thumb.png.66218633cd3d60fea6d5f8a66277c1e0.pngimage.thumb.png.b6a48c70bb353c48e04b4901974e6928.pngimage.png.b964e4ced78a6d378ee59ed8847f1d81.png

In the second case, the color of the line doesn't transition correctly, or at all really. The weight transitions fine, but the color stays either constant or varies very slightly (as shown in the third picture). Perhaps more bizarrely, if I set the color instead to be a random color, the lineStyle seems to adjust correctly (although the colors don't seem nearly random enough. Additionally, if I set the color to be some aspect of the index of the loop I'm drawing in (like setting the hue to be (i * 20 % 360)), I get  these weird color bands that seem to want to jump back to previous colors. I stepped through the batching code and could not figure out for the life of me where these colors were disappearing. I would love some help as to figuring out this problem because I am completely stumped.
 image.thumb.png.b8cb8b52e251aabb11591afd4a8caeb5.pngimage.thumb.png.e5f5468f725574585f15818157a74338.png

image.png

I'm using the development build of Pixi v6.0.1.

Link to comment
Share on other sites

Adding more features to Graphics, making it smooth and color transitions is one of hardest tasks related to PixiJS and WebGL 2d graphics. Even I am stuck with one of such tasks for 6 months already.

The main problem is that when someone does that kind of improvement or solves particular tasks - he doesnt share it, and next person has to re-invent it.

As a result, those tasks are real paid work, dont expect people to just help with it. Maybe someone will share his experience in the topic, but dont count on it.

Link to comment
Share on other sites

Okay, fair enough I guess I'm just confused because the behavior seems to be inconsistent. If I draw the entire line in one frame, then the color transition works fine. But when I draw it across multiple frames, it seems to reference previous line style colors rather than using the newly declared line style each time. I'll continue to look into it and post here if I get any findings. Thank you.

Link to comment
Share on other sites

Alright so I've found a solution and also may have found the root of the problem while digging through the graphics code. I'm unsure if this is due to some batching problem but here's the issue that I've found(I'd be happy to post more on GitHub if this is actually an issue). I've included the table below that showcases the problem.

idx	 	#Colors		#Verts		#Batches
0		0		0		0
1		0		8		1
2		0		24		2
3		0		32		3
4		0		48		4
5		0		64		5
6		0		80		6
7		0		96		7
8		0		112		8
9		0		128		9
10		0		144		9
11		0		160		10
12		0		168		11
13		0		184		11
14		0		192		12
15		104		208		14
16		212		216		14
17		328		232		15
18		448		240		16
19		572		248		16

Each of these columns (besides the index) represents the length of the GraphicsGeometry's colors, points, and batches arrays, respectively. Every time we add a new line segment we add 8-16 numbers (x, y) which should presumably come with 4-8 color values, one for each vertex. And this works fine the first time that buildDrawCalls() is called, which in this case happens after 12 batches have been added to the geometry, so we get the proper numbering (on idx 15) where the number of colors in the geometry is 104 = 208/2. Then when this is passed to packAttributes(), each vertex is assigned the correct color.

However, on the next buildDrawCalls() at idx 16, this.addColors(...) is called again for every single one of the geometries batches, despite it only adding 4 vertices. Therefore, when packAttributes is called, the vertices that were added are now colored by the colors that are supposed to be associated with the first few vertices in the list. I've included a diagram of what I'm trying to describe in case my description is confusing.
H7nCnLA.png

 

I'm not sure if this is a problem with the way I'm using my graphics objects, but this causes the colors array to quickly get out of hand and become far larger than the number of vertices. With 68 line segments the number of colors goes to around 28000, when we really only need around 300 of those, so most go completely wasted.

As a patch for this, I simply clear the colors array of the geometry every time I add a line segment. Since buildDrawCalls() currently re-adds all the colors anyways, it seems like this shouldn't cause an issue, and would actually be more efficient.

I'm curious to know if this is a real bug or caused by something that I'm doing wrong.

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...