"Crop" WebGL Shader?

  • Hi!

    tl;dr I really want to write a "Crop" shader, any pointers? :P

    So I have literally no experience with writing GLSL shaders, or ANY shaders for that matter. I'm trying to create a (seemingly) simple "Crop" shader. I've been looking through the documentation and files that Scirra provides, but I can't seem to wrap my mind around it!

    I then found my ol' files from MMF2 which had a similar "Crop" shader (Not owned by me, part of the "Complex-softwares" pack I downloaded yearrrrs ago) that I decided to edit and tinker with to figure out how to port the shader into the GLSL language.

    Since I'm not entirely understanding what I am doing (I get a few things but barely anything), I have ended up trying many different combinations of words and replacing things here and there, and I simply can't get it to work. I have failed to get any sort of effect EXCEPT making my sprite's alpha channel get affected. I guess that's something!

    So the way this particular crop works, is that you get several parameters to edit (Left, Right, Top, Bottom, Alpha). You would specify the amount of pixels to modify from each parameter, and then the alpha would transform those pixels to the alpha specified.

    So say you have this sprite:

    <img src="https://dl.dropboxusercontent.com/u/7765312/C2/Croppy/1.png" border="0" />

    And you then set "Bottom" to something like 10, and Alpha to 0, it should give this result:

    <img src="https://dl.dropboxusercontent.com/u/7765312/C2/Croppy/2.png" border="0" />

    I will attach what I've attempted, I'm pretty eager to learn about how to actually solve this and how it works. If it's also much to ask for, I'd LOVE to be able to retain the angle if the sprite is rotated; so following the previous example with Bottom and Alpha, the crop would appear like this when the sprite is rotated:

    <img src="https://dl.dropboxusercontent.com/u/7765312/C2/Croppy/4.png" border="0" />

    IN AN IDEA WORLD: If I was a pro shader writer, I wouldn't make this exact shader for Crop, I would instead, have only 2 parameters, "Amount" and "Angle", in which you specify an angle in which the crop will come from, and "Amount" would be how many pixels it crops off (That way, You could specify 45degree angles whilst the sprite's angle is 0.)

    Here's my failed attempt (along with the shader I'm trying to port):

    dl.dropboxusercontent.com/u/7765312/C2/Croppy/crop.zip

    Thanks!

  • Bumpity bump.

    Any sort of advice would be greatly appreciated! I have read the documentation supplied from Scirra but I'm having a hard time for something that sort of looks like it'd be extremely easy to figure out if one had prior knowledge about shader writing.

  • Jase00 : I gave a look to your shader. For the moment, it does what you want. If you want to crop an "amount", you can ask the user to give the amount as a percentage. Then you have a number between 0 and 1 that you can use as a condition for fL, fR, fT and fB directly. For the angle, it's less obvious, you need to use some trigonometry.

  • digitalsoapbox , thanks! I haven't checked that out actually, I will give it a look! Though I still hope to figure out my situation, would be handy to gain some knowledge on Shader writing as well as this would directly fit what I need in my project at the moment

    @Pode , Hey thanks for checking it out! But,...well, it's broken haha. I uploaded it fully knowing it's not working as expected, but it's an attempt nonetheless. If you enter any value into any of the parameters, it will not crop at all, it will just set the transparency to whatever Alpha value is set.

    If you set "Left" to 0, the sprite will just look normal.

    Set "Left" to 1 and the entire sprite will go to whatever Alpha is specified.

    Set "Left" to 0.09, and the outer edge of the sprite will turn into the Alpha specified.

    So in conclusion, it's broken...

    I figured doing the angle version of this shader would require Trig, and I think I know the math to do it, I just don't understand at all how to implement it in shader language at all I figured if I could get this "Left Right Top Bottom" version figured out, I would have a better chance at the Angle version.

    Thanks for response! I appreciate it greatly!

  • There's a couple of issues with your shader:

    • First you are not using brackets in your if statement, so the alpha is set for every pixel and the if is effectively doing nothing.
    • Second you are using front.x and front.y, that is the same as front.r and front.g respectively, and those returns color values and not positions. What you meant to use is vTex.x and vTex.y that are the coordinates.
    • Just a minor thing, but you can multiply the alpha value directly (front.a *= fA) instead of repeating the alpha then multiplying (front.a = front.a*fA).

    So your code should look like this:

    lowp vec4 front = texture2D(samplerFront, vTex);
    
    if( vTex.x<fL || vTex.x>1.0-fR || vTex.y<fT || vTex.y>1.0-fB )
    { front.a *= fA; }
    
    gl_FragColor = front;[/code:2pirw3zx]
  • Wow, thank you so much Animmaniac ! This is extremely helpful and has helped me understand a bit more about writing shaders

    I didn't expect that the effect is applied BEFORE rotations (as in, apply this shader, then change the sprite's angle, the shader rotates too, which is what I wanted ) , so that's awesome!

    There's only 1 problem with the shader (which I'm struggling to understand why it's happening), and that is that it's not affecting certain colours correctly (Black would crop correctly, white is still visible). I reckon I've probably mucked up with the brackets somehow in the entirety of the shader or something.

    Here's a copypasta of the entire shader code, just incase I've mucked up something simple:

    // Pixel shader input structure
    varying mediump vec2 vTex;
    uniform lowp sampler2D samplerFront;
    uniform mediump float pixelWidth;
    uniform mediump float pixelHeight;
    uniform mediump float fL;
    uniform mediump float fR;
    uniform mediump float fT;
    uniform mediump float fB;
    uniform mediump float fA;
    
    void main(void)
    {
    lowp vec4 front = texture2D(samplerFront, vTex);
    
    if( vTex.x<fL || vTex.x>1.0-fR || vTex.y<fT || vTex.y>1.0-fB )
    { front.a *= fA; }
    
    gl_FragColor = front;
    }
    [/code:hec086l3]
    
    And here is a screenshot of the problem.
    [img="https://dl.dropboxusercontent.com/u/7765312/C2/Croppy/croppypy.png"]
    
    I'll poke around with it but I'm not sure if it's not an obvious fix
  • Did you manage to fix the issue?

    I know nothing about glsl, but I'm pretty good with trigonometry, so if you need some help there send a PM.

  • I've not managed to solve this and not quite sure what to do

    Does anyone have any good reading material for GLSL? I remember looking at a PDF file I found but I couldn't figure much out.

  • This could have been really useful for me, so I'm going to take some time to try to fix it.

  • Sorry for not helping earlier, I totally forgot about this topic.

    Here's a fixed version of the shader:

    Fixed Crop Effect

    C2 uses pre-multiplied textures, which means the RGB color values are stored multiplied by the alpha value.

    So to avoid glitches you first need to divide the RGB by the alpha to get the real color values, then you do your pixel manipulation, and multiply the RGB by the alpha again at the end.

  • Animmaniac

    Woah!! That is exactly what I was trying to get all along!!! Ah it makes much more sense, I was so confused with the weird semi-transparent result from my own experiments Thank you very much!

    I only need to figure out 2 more things and that's it . I reckon I might find some info to study from looking at other shader files but if you have any pointers considering you seem to know your way around this sort of thing, I'd be very grateful!

    The first being, how would I be able to set the value according to number of pixels from the side? So if I set R to 7, it would trim 7 pixels off of the right side of the Sprite.

    The second being, how would I incorporate Angles into this shader? If I had another variable called "AngleOfCrop" which is set to like 15 and "R" is set to 9, it would trim the right side 9 pixels, but at a 15degree angle. Below is a picture to explain (The Red part is the part that will be invisible from the crop) [EDIT: I realised that this little diagram might not be correct. I need to rethink the theory behind what I'm trying to explain.]

    I think this part is going to be harder to do than the original non-angled crop. It doesn't help that I barely know how shaders work but it's something I'm interested in and am picking up on information from reading documenation, looking at other existing shaders, and reading your replies. Thank you for your time!

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • To set the crop based on pixels rather than a percentage, you only need to multiply the values by pixelWidth and pixelHeight. This converts from object-space to screen-space. If you do this, remember to change the parameters from "percent" to "float".

    Now to set an angle is a lot more complicated. I think you will need to use the line equations to check at which side of the crop line the pixels are, based on the angle and distance from the center. If you do a naive check (to right of the line opaque and to left transparent) you will probably get a pixelated line. So to get a smooth line you will need to think in a mathematic function that returns a value between 0 and 1 depending on the distance of the pixel to the crop line, so you get an anti-aliasing.

    There's probably other ways to achieve it. But either way, when you put angles and different coordinate spaces into the mix things get a lot harder.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)