Post-Processing Shaders in Godot 3.5 - A Depth Buffer Exploration

Поделиться
HTML-код
  • Опубликовано: 8 сен 2024

Комментарии • 62

  • @Z_Z.
    @Z_Z. Год назад +23

    Small note: If youre using godot 4.0 and POSITION = vec4(VERTEX, 1.0); doesn't work, you can use POSITION = vec4(UV*2.0-1.0, 0.0, 1.0);

    • @wattinteractive
      @wattinteractive  Год назад

      Oh, thanks for the tip! I'll keep it in mind for future Godot 4 videos👍

    • @Keimoj
      @Keimoj Год назад +1

      @@wattinteractive

    • @akatuoro
      @akatuoro Год назад +7

      POSITION = vec4(VERTEX, 1.0); still works in Godot 4, but 'Flip Faces' needs to be enabled on the QuadMesh

    • @ferenccseh4037
      @ferenccseh4037 9 месяцев назад

      Thank you, I thought I was going crazy

    • @cookie_884
      @cookie_884 Месяц назад

      thank you bro

  • @DevLogLogan
    @DevLogLogan 2 года назад +3

    Very enjoyable and informative video, looking forward to more content like this. :)

  • @MasonDavies74
    @MasonDavies74 9 месяцев назад +1

    Excellent tutorial, thank you!
    If anyone else wants to use this effect with an Orthographic camera, I have a solution. I'm pretty new to shaders, so there's probably a better way, but this worked for me.
    you will want to tweak your Camera's Far value, and maybe its distance from the scene-otherwise you might get some strange clipping.
    I ended up moving my Camera out to z=100, and setting its Far to 130 (my camera is tilted at 30 degrees but I assume the similarity of these numbers is a coincidence). Experiment with your camera's near, far, and position, and eventually you should find some values where the whole shader mesh and scene are visible.

    • @wattinteractive
      @wattinteractive  8 месяцев назад

      You're welcome! And thanks for the tips!

  • @ncarter76
    @ncarter76 5 месяцев назад +1

    For the second half of the video, if you're in Godot 4, CAMERA_MATRIX is now INV_VIEW_MATRIX.

  • @huraqan3761
    @huraqan3761 Год назад +1

    Thanks for the tutorial, great stuff!
    I read that it's best to avoid "if" statements inside shaders and instead favor using equivalent mathematical functions. Something about wavefronts in parallel processing. Basically when every fragment executes the same code, then everything can keep running in parallel (as one wavefront). But if some fragments have different conditions, then it slows down the whole parallel schtick (creating new wavefronts)

    • @huraqan3761
      @huraqan3761 Год назад

      Just to clarify, "if is_running" would not slow down parallel processing. But "if d > max_d" for example could be replaced by a function

    • @wattinteractive
      @wattinteractive  Год назад

      Interesting, I'd not heard it put that way before but it makes sense to me and I'll keep that in mind for future tutorials/revisit this effect with that in mind. Thanks for the tip! 👍

  • @knowercoder
    @knowercoder 4 месяца назад

    This is very useful. Thank you!

  • @redalchemy7322
    @redalchemy7322 Год назад

    This would be very useful to make some pre-rendered backgrounds! Thank you for the video

    • @wattinteractive
      @wattinteractive  Год назад +1

      You're very welcome! I'm glad it was helpful 😄

  • @nyeeesss2424
    @nyeeesss2424 Год назад

    Underrated video

  • @wattinteractive
    @wattinteractive  10 месяцев назад +1

    If anyone is looking for this effect in Godot 4, I've updated the GDScript and the Shader code at Godot Shaders. Link in the description ☝️

    • @sebastianromejko4652
      @sebastianromejko4652 2 месяца назад

      You just saved my life! I've already spent like 2 hours trying to adjust the old shader to Godot 4 with poor results... Thanks for awesome shader!

  • @mvolkankarakas
    @mvolkankarakas 2 года назад

    You are good ... please keep proceed

  • @mikecu2249
    @mikecu2249 10 месяцев назад

    that was rly good!

  • @my2cents795
    @my2cents795 9 месяцев назад +1

    Hello, this doesn't work when there is semi transparent objects in the scene. Would you mind making a tutorial for passing a viewport texture as a shader parameter to achieve a similar result but also show semi transparent objects ? I'd be eternally grateful :)

    • @wattinteractive
      @wattinteractive  9 месяцев назад +1

      Ooh... interesting, I didn't of that. That sounds like a fantastic improvement to the shader, let me add that to the top of my list of topics to look at. Thanks!👍

    • @my2cents795
      @my2cents795 9 месяцев назад

      @@wattinteractive Brilliant ! I'll be looking forward to it ! subbed and hit the bell :)

    • @wattinteractive
      @wattinteractive  9 месяцев назад

      @@my2cents795 Thanks! 😁👍

    • @wattinteractive
      @wattinteractive  9 месяцев назад

      Okay, so it looks like this will end up being a quite involved project to get it to fully work properly (seemingly due to the way Godot handles rendering transparency? Still looking into that), but I did find in playing around that if you set the render priority to -1 for the post-processing material, it should render the semitransparent objects, but they won't interact with the shader. Hopefully that's enough to get you by for now while I try and find a better solution! 👍

    • @my2cents795
      @my2cents795 9 месяцев назад

      ​@@wattinteractive Ohhh, nice! That could work for now. I'm doing fog of war post processing shader for my RTS game (video coming out soon) and I have a few semi transparent assets but they all belong to the player so they should all be in the visible area of the fog of war (no need to be affected by the shader) but in the future, enemy units/buildings might have some semi transparent objects that need to be hidden in the fog of war still. I've browsed through the Godot github and found a few changes in the pipeline that allow for post transparency screen capture. Hopefully they are merged soon. Thanks a lot for the brilliant temporary solution :)

  • @AlessandroCarraro
    @AlessandroCarraro Год назад +1

    Can't understand well the scaled depth variable and how i should tune the zFar and zEnd variable... what is its range? I'm trying to achieve a result similar to the one of the first part of the video, but what I'm looking for is a "color" from 0 to full white, where 0 is everything farther than X (or background) and white means distance 0, and I'd like to have it linear..
    Is the formula provided linear? Many thanks

    • @wattinteractive
      @wattinteractive  Год назад

      So, I'm having trouble understanding exactly what you're looking for with the effect, but to try and answer your questions:
      1. Yes, the formula is linear. It's purpose is just to re-scale the value that is retrieved from the depth buffer into something with more human understandable numbers.
      2. In theory, zNear should be the distance away from the camera the effect starts, and zFar is telling the equation how far away the "max" effect should be. My demo scene is very small so I didn't get the chance to fully test it.
      3. Now, to get the effect I think you want, you'll need to read the screen texture (like I do in the pulse section) and then mix it with a white color using the scaled depth value. It would be something like:
      -----
      vec4 original = texture(SCREEN_TEXTURE, SCREEN_UV);
      vec3 white = vec3(1.0);
      ALBEDO = mix(white, original.rgb, scaled_depth);
      -----
      If I misunderstood what you're looking for let me know what I missed and I'll try and answer again.

    • @AlessandroCarraro
      @AlessandroCarraro Год назад

      ​@@wattinteractive thank you very much. I've been very busy so I could recheck everything only today.
      There are 2 issues to me, right now. 1 linear_depth isn't the distance it is negative! I think it is negative in your implementation too, because in your scaled_depth implementation you are multiplying for a negative factor (zNear - zFar). 2, I got the formula "right", since I make it work as intended in the preview, but running the project the shader show it pitch black. Here is my modified shader:
      shader_type spatial;
      render_mode unshaded;
      uniform float zNear = 2.0;
      uniform float zFar = 30.0;
      void vertex(){
      POSITION = vec4(VERTEX, 1.0);
      }
      void fragment(){
      vec4 original = texture(SCREEN_TEXTURE, SCREEN_UV);
      float depth = texture(DEPTH_TEXTURE, SCREEN_UV).x;
      vec3 ndc = vec3(SCREEN_UV, depth) * 2.0 - 1.0;
      vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
      view.xyz /= view.w;
      float linear_depth = view.z;
      float scaled_depth = (zFar * zNear) / (zFar + (linear_depth * (zNear - zFar)));
      ///////////////// up to here it should be identical to yours///////////////
      float inverted_depth = -linear_depth; // because I found that linear_depth is negative
      ///////// limit inverted_depthto b in range [zNear, zFar]
      if(inverted_depth > zFar)
      inverted_depth = zFar;
      else if(inverted_depth < zNear)
      inverted_depth = zNear;
      //////// end limiting
      // zNear < inverted_depth < zFar;
      if(SCREEN_UV.x < 1.0)
      ALBEDO = vec3(1.0-((inverted_depth-zNear)/(zFar-zNear))); //the formula I want to work. SINCE zNear < inverted_depth < zFar, IN THEORY SHOULD BE IN RANGE [0,1]
      if(SCREEN_UV.x < 0.55)
      ALBEDO = vec3(scaled_depth); // your formula
      if(SCREEN_UV.x < 0.5)
      ALBEDO = original.rgb; // original rgb to check that the camera is actually pointing to the right spot
      }
      In preview mode, everything looks as they should be, ingame rgb and your formula look the same, my formula output only black pixels

    • @wattinteractive
      @wattinteractive  Год назад

      I've given your shader a try and it works for me so unfortunately I don't have any specifics that can help solve the problem you're running into. I would say, as a general piece of troubleshooting, try using "clamp" to make sure values are in the range they're supposed to be, and double check that your "zFar" value is large enough that objects are within range to be seen.
      Also, you are correct that distance can't be a negative value, I could have been more accurate when talking about linear_depth, apologies for the confusion. In this case it is the z value of the position vector with the origin centered on the camera, and because the camera in godot looks along the -z axis, it results in a -value.

    • @AlessandroCarraro
      @AlessandroCarraro Год назад +1

      @@wattinteractive thank you for you time. It took A LOT (many hours of tests), but I figured out the problem. The error was outside the shader, a gd-script passed IDIOT numbers to he uniforms (zNear ~= zFar) so that only a silly slice of distance was enabled (and was so near the camera to be always empty).... the reason I saw the correct things in the preview was that it takes the correct values setted in the mesh instance propreties, but then those values were overwritten witn nonsense :( !

    • @wattinteractive
      @wattinteractive  Год назад +1

      Oof, yeah that's a rough one to debug, but I'm glad you were able to solve your issue! 😄

  • @kron520
    @kron520 2 года назад +1

    For some reason, the full-screen-quad method doesn't work in Godot 4.0.

    • @wattinteractive
      @wattinteractive  2 года назад +1

      Oh, thanks for letting me know! I haven't found time to played around with the 4.0 branch yet, but I'll update the title to reflect the version that I'm using (3.5).

    • @kron520
      @kron520 2 года назад

      @@wattinteractive Maybe it's just the current alpha-build, or the whole rendering pipeline has changed. Who knows!?
      Works perfectly in 3.x and was very helpful.

    • @wattinteractive
      @wattinteractive  2 года назад

      I'm glad to hear it 😄

    • @DevLogLogan
      @DevLogLogan 2 года назад +5

      I'm not sure if culling is disabled on quad meshes by default in 3, but the back face is culled by default in 4. If you set the render_mode to include either cull_front or cull_disabled, it should work!

    • @kron520
      @kron520 2 года назад

      @@DevLogLogan It does!

  • @alanbeyersdorf7471
    @alanbeyersdorf7471 2 года назад

    Hey there! I wanted to thank you for making a great tutorial. It was really easy to follow and funny at times, too! I have a question: how do I set it so that the scanner is alway projected from a first person camera. I want it to be as if the player is scanning.
    So far, I have it set from the camera, but it only resisters from the players starting position. If the player moves, the scan stays at the spawn point and never moves. How to get the scan to attach to the player and move with them?
    Thank you for your help!

    • @wattinteractive
      @wattinteractive  2 года назад +2

      In the script attached to the Quad Mesh, I have it only setting the "start_point" parameter of the shader in the _ready function. If you want it to update to where your player is when it's started, you'll also want to set the "start_point" when the input is detected.
      I guess you could also keep setting it as the effect is running, but that would change how it looks if the player also moving at the same time. Probably isn't the effect you're looking for, but maybe something to experiment with.
      And thanks for checking out the video! 😄

    • @alanbeyersdorf7471
      @alanbeyersdorf7471 2 года назад

      @@wattinteractive I was able to get this to work! Thanks again for making this tutorial. I have been looking for a tutorial on this mechanic for a while. Everything you showed maded sense and was easy to follow. I hope you continue making tutorials for Godot!

    • @wattinteractive
      @wattinteractive  2 года назад +1

      Yay! I'm happy to hear it's working now. And yes, I'm certainly planning on making more videos... they just take a while to make 😅

  • @jumageorge5405
    @jumageorge5405 Год назад

    Very good video..how do i set so that instead of drawing a circle, i draw a rectangle..I was thinking of using your idea but as lights underneath my vehicle

    • @wattinteractive
      @wattinteractive  Год назад +1

      Oh, interesting question that I don't currently know the answer to. My first thought is that it might be easiest to just use lights underneath the vehicle, but I assume you've already tried that and it's not looking how you want it to.
      My second thought is that there's something called Signed Distance Fields (SDF) that might be what you're looking for. I'll add it to my schedule to look into, but it might be a while before I can get back to you.
      In the meantime, let me know if you figure it out; I'm curious to know the solution you came up with.

    • @jumageorge5405
      @jumageorge5405 Год назад +1

      Well I'll let you know when I succeed.
      Anyway, I also looked everywhere for a color rect shader that blurs around a glowing object but coldnt find one. This shader might as well enhance our gles2 visuals in terms of bloom and emission

    • @wattinteractive
      @wattinteractive  Год назад

      If you haven't already come up with another solution, I figured out how to do what I think you were asking for and made a video about it: ruclips.net/video/0BXBXy8zaaI/видео.html
      I hope it helps!

  • @blankink
    @blankink 8 месяцев назад

    is it possible to have multiple instances of pulses each at a different place, at the same time?

    • @wattinteractive
      @wattinteractive  8 месяцев назад

      Yes, you can add variables to pass in the start location of the other pulses (and other timings if you want). You then also need to add another conditional statement for the pulses you want to add. I know they were looking at passing arrays to the shader in Godot 4 which could make this easier, but I haven't followed up on the status of that.

    • @adrianhusar
      @adrianhusar 4 месяца назад

      Hi @blankink, were you able to figure this out? I'm looking into the same thing :)

    • @blankink
      @blankink 4 месяца назад

      @@adrianhusar I went with a completely different shader I used the cut off shader with a boder to it instead

  • @meabefir6639
    @meabefir6639 Год назад

    Any idea why this doesnt work with GLES2?

    • @wattinteractive
      @wattinteractive  Год назад

      Not off the top of my head. Let me look into it and I'll try to get back to you with an answer

  • @theafroguys5231
    @theafroguys5231 9 месяцев назад

    is it posible to make multiple rings at the same time?

    • @wattinteractive
      @wattinteractive  8 месяцев назад

      Yes, it is definitely possible to make more rings. You'll just need to do another check of the distance and start point and then mix that in to the albedo as well.

  • @tomashutchinson2025
    @tomashutchinson2025 Год назад

    nice 3090