-
Notifications
You must be signed in to change notification settings - Fork 444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix flxstrip color causing not rendering other flxstrips #3220
Conversation
…g the same shader.
Hello, it would be really helpful if anyone can consider reviewing this PR. |
Sorry, was dealing with family stuff This PR seems to work in all my tests, I just wanna discuss a couple things, firstly, this odd behavior: Screen.Recording.2024-08-13.at.2.12.01.PM.movNote: tint on the last mesh behaves as described, but the same happens for the first and then by colorizing two meshes it suddenly works on all future frames for all configurations. Now, your fix prevents all of this weirdness, I just thought I'd bring it up in case this means anything to you Secondly, can you elaborate on what the
I'm not really well-versed in flixel's rendering, or rendering in general, could you elaborate on what you're proposing here? Specifically, if we were to implement your proposal, would that be a separate issue altogether, or would that effect this PR, which I'm ready to approve |
No need to say sorry! Family stuff wins over everything :)
I do not have access to your code example. When I tried to repro your example, it behaved in a different bugged way. This is the flixes shader: precision mediump float;
attribute float openfl_Alpha;
attribute vec4 openfl_ColorMultiplier;
attribute vec4 openfl_ColorOffset;
attribute vec4 openfl_Position;
attribute vec2 openfl_TextureCoord;
varying float openfl_Alphav;
varying vec4 openfl_ColorMultiplierv;
varying vec4 openfl_ColorOffsetv;
varying vec2 openfl_TextureCoordv;
uniform mat4 openfl_Matrix;
uniform bool openfl_HasColorTransform;
uniform vec2 openfl_TextureSize;
attribute float alpha;
attribute vec4 colorMultiplier;
attribute vec4 colorOffset;
uniform bool hasColorTransform;
void main(void) {
openfl_Alphav = openfl_Alpha;
openfl_TextureCoordv = openfl_TextureCoord;
if (openfl_HasColorTransform) {
openfl_ColorMultiplierv = openfl_ColorMultiplier;
openfl_ColorOffsetv = openfl_ColorOffset / 255.0;
}
gl_Position = openfl_Matrix * openfl_Position;
openfl_Alphav = openfl_Alpha * alpha;
if (hasColorTransform) {
openfl_ColorOffsetv = colorOffset / 255.0;
openfl_ColorMultiplierv = colorMultiplier;
}
}
It declares the vertex attribute
If this attribute is enabled, the shader expects this vector to be populated with a number of colors corresponding to the number of vertices (1 RGBA x vertex). As far as I saw, custom attributes are set directly into the shader in flixel. In this case we do:
For triangles batching, the code uses a high level representation named
This Consequently, in the
If we do not nullify its value as in the else, we are asking to the shader to use those colors.
That's not a performance fix, that's another bug :D Since we need to pass a color per vertex, but the color transform of the `FlxStrip holds a single color, the code loops over the number of vertices and adds for each vertex the color (and the alpha in the loop above). However, the loop is using the wrong variable to loop! Currently is uses
The expected result would be:
The same thing happens for alpha. However, that's a bug because some vertices of the batch would use the wrong colors. In this case the third
The easiest way to render is to make a draw call per Colors and alpha are vertex attributes, not uniforms. So there is no apparent reason to me to break the batch for that. Hope everything is clear, let me know if you need any additional clarifications :) |
cool, make one whenever you like Here's the test I made, BTW package states;
import flixel.FlxG;
import flixel.FlxStrip;
import flixel.group.FlxGroup;
import flixel.graphics.FlxGraphic;
import openfl.Vector;
class FlxStripColorTestState extends flixel.FlxState
{
final meshes = new FlxTypedGroup<Mesh>();
override public function create()
{
super.create();
for (i in 0...3)
meshes.add(new Mesh(10, 10 + i * 110));
add(meshes);
}
override function update(elapsed:Float)
{
super.update(elapsed);
if (FlxG.mouse.justPressed)
{
final mouse = FlxG.mouse.getWorldPosition();
for (mesh in meshes)
{
if (mesh.overlapsPoint(mouse))
mesh.toggleColor();
}
mouse.put();
}
}
}
@:forward
abstract Mesh(FlxStrip) to FlxStrip
{
static inline var ON_COLOR = 0xFFffff00;
static inline var OFF_COLOR = 0xFFffffff;
inline public function new (x = 0.0, y = 0.0)
{
this = new FlxStrip(x, y);
this.makeGraphic(50, 50, 0xFFff80ff);
this.width = 100;
this.height = 100;
this.indices = Vector.ofArray([0, 1, 2, 0, 2, 3]);
this.vertices = Vector.ofArray([0., 0., this.width, 0., this.width, this.height, 0., this.height]);
this.uvtData = Vector.ofArray([0., 0., 1., 0., 1., 1., 0., 1.]);
this.color = OFF_COLOR;
}
public function toggleColor()
{
this.color = (this.color == OFF_COLOR ? ON_COLOR : OFF_COLOR);
}
} |
Thanks! |
When multiple FlxStrip are rendered using the same shader, if one of them uses the
color
property, it causes the other meshes to not be rendered.Here an example:
Commenting and uncommenting the
mesh3.color = -9306137;
line, it will trigger the bug.In this example
mesh1
andmesh2
are added to the same triangles batch. A second triangle batch is created formesh3
.Here wath happens at the first render iteration:
shader.colorMultiplier.value
isnull
. The draw call happens and the two meshes are visible.shader.colorMultiplier.value
is set using thecolorMultipliers
of the batch. The draw call happens and the third mesh is painted over the others two.Then the second iteration happens. Canvas is cleared and:
shader.colorMultiplier.value
has the previous values set by the second batch. The draw call and I guess since there is a number of colors that does not match the number of vertices, nothing is rendered for this batch.Same occurs for the next iterations.
This PR reset
shader.colorMultiplier.value
andshader.colorOffset.value
tonull
, if there is no color multipliers or offsets.I'm not entirely sure if that is the right place to reset these values. There is the batch
reset
method, but theshader
is alreadynull
in that context, even though I could acces thegraphic.shader
, before thesuper.reset()
is called.Moreover, I've noticed that during the fill of color multipliers and offsets, the iteration occurs for all the indices in the batch, rather then the indices of the added triangle. This PR fix also that.
I'd like also to ask if there is any specific reason why color (and alpha) tinting, a new batch is initiated.
In my example, we need two draw call to render the three meshes. If we remove avoid to start a new batch when the mesh is colored through
color
oralpha
, we can prevent to break batching. What do you think about this?