-
Notifications
You must be signed in to change notification settings - Fork 22
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
Feat: Add distort shader #271
base: main
Are you sure you want to change the base?
Conversation
topLeft: props.topLeft || { x: 0, y: 0 }, | ||
topRight: props.topRight || { x: 1920, y: 0 }, | ||
bottomRight: props.bottomRight || { x: 1920, y: 1080 }, | ||
bottomLeft: props.bottomLeft || { x: 0, y: 1080 }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These defaults are a bit too specific. I think one thing you might be able to do to achieve this dynamically is to allow null
as value for each of these keys and make null
the default. Then in bindProps
I think you could check for null
and dynamically create the defaults using the $dimensions
property which at that point is reliable. (Going to leave a separate comment in regards to your request for comments on potentially using normalized 0.0 -> 1.0 values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I think that approach is nice. I was calculating the normalized values in the shader code but this works. To get this working using null
I had to modify the Point
class to accept number and null types. Allowing null
feels a bit weird to me. I could keep it as number only and the default be zero, then if I see a zero size width or height value assume its been left as zero on purpose and use the full width/height? What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd regard the whole Point as a unit. The type of each corner in that cause would be Point | null
. So if you need to provide an x
, you also need to provide the y
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah that makes sense, I'll change it 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@frank-weindel Done!
@lewispeel Awesome work. Thanks for the contribution. Regarding your question about potentially using relative normalized values instead of absolute position values, I'd say allow both. I can see both methods coming in handy depending on the situation. You could base it off of a new boolean prop flag ( Please let me know if you need assistance generating the certified snapshot needed for this. You need to run the visual regression test runner in |
revert formatting
@frank-weindel Thanks for the feedback! I've got it working with both pixel and normalized values. Something to note, see line 132 in |
// if the dimensions create a rectangle, nothing is rendered | ||
// adding a small amount to one of the x values resolves this | ||
if (topLeft[0] === bottomLeft[0] && topRight[0] === bottomRight[0]) { | ||
topLeft[0] = +0.0001; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small typo here, you're now assigning 0.0001
to top-left x position. You probably meant:
topLeft[0] += 0.0001
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks @erikhaandrikman - I removed this block as the fix you suggested below means I don't need this anymore.
return a.x * b.y - a.y * b.x; | ||
} | ||
|
||
vec2 invBilinear(in vec2 p, in vec2 a, in vec2 b, in vec2 c, in vec2 d ){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent the rendering issues when the axis are perpendicular ( like you mentioned in your comment ) you can replace in inverse bilinear function for:
vec2 invBilinear( in vec2 p, in vec2 a, in vec2 b, in vec2 c, in vec2 d )
{
vec2 e = b-a;
vec2 f = d-a;
vec2 g = a-b+c-d;
vec2 h = p-a;
float k2 = xross( g, f );
float k1 = xross( e, f ) + xross( h, g );
float k0 = xross( h, e );
float w = k1*k1 - 4.0*k0*k2;
if( w<0.0 ) return vec2(-1.0);
w = sqrt( w );
// will fail for k0=0, which is only on the ba edge
float v = 2.0*k0/(-k1 - w);
if( v<0.0 || v>1.0 ) v = 2.0*k0/(-k1 + w);
float u = (h.x - f.x*v)/(e.x + g.x*v);
if( u<0.0 || u>1.0 || v<0.0 || v>1.0 ) return vec2(-1.0);
return vec2( u, v );
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing! Thanks @erikhaandrikman - this is fixed.
@lewispeel This needs a snapshot generated with:
Check out the |
@erikhaandrikman I've just spotted a problem.. this demo works fine on single nodes with no children, but if I create a node with child nodes (requiring To test this, comment out lines 93-95 in |
Thanks Frank, I'll wait for Erik to feed back on the issue above and I'll make sure to run the visual tests 👍 |
probably due to the fact that the render texture is render flipped ( and coords being restored before pushing them to the buffer )
i can look into this |
We're encountering some projection issues, primarily with text, when attempting to flip the rendering in render texture nodes. As a temporary solution, we've been rendering the contents to an extra childNode (with RTT enabled) and flipping the rendering on the Y-axis by setting
|
@erikhaandrikman can we move this along with known limitations of RTT? |
I recently created a shader In Lightning 2 to distort a texture inside itself and ported it to Lightning 3. It allows you to define new coordinates for top-left, top-right, bottom-right and bottom-left inside it's original dimensions.
Changes
DistortShader
to WebGL shaders (based on https://www.shadertoy.com/view/lsVSWW).Point
interface toCommonTypes
to make shader params typesafe.examples/tests/distort-shader
that shows using pixel values and normalized values.CoreShaderManager
to includeDistortShader
as an option.How to test
pnpm start
http://localhost:5173/?test=distort-shader
Usage
You can use explicit pixel values or normalized values e.g.
{ x: 0.5 }
will be 50% of the texture width. To use normalized values, addnormalized: true
to the shader parameters.Output
Examples using pixel values (left), normalized values (right). The dark rectangle are to illustrate where the original dimensions of the image textures.