How To Render CIRCLES (OpenGL/Vulkan/DirectX/Metal)

แชร์
ฝัง
  • เผยแพร่เมื่อ 7 ก.ย. 2024
  • Patreon ► / thecherno
    Instagram ► / thecherno
    Twitter ► / thecherno
    Discord ► / discord
    Code ► www.shadertoy....

ความคิดเห็น • 264

  • @TheCherno
    @TheCherno  2 ปีที่แล้ว +82

    Hope y’all enjoyed the video! What topic do you want to see me cover next?

    • @antontheyeeter
      @antontheyeeter 2 ปีที่แล้ว +1

      Maybe spheres

    • @alexisloic21
      @alexisloic21 2 ปีที่แล้ว +1

      Torus

    • @ChlorieHCl
      @ChlorieHCl 2 ปีที่แล้ว +8

      SDF font rendering

    • @70elysium
      @70elysium 2 ปีที่แล้ว +1

      Hierarchical transforms in ECS would be great.

    • @TheBigWazowski
      @TheBigWazowski 2 ปีที่แล้ว +1

      Network code would be interesting to learn about

  • @fmdj
    @fmdj 2 ปีที่แล้ว +276

    You don't need the square root, sqrt(x^2 + y^2) < 1 is equivalent to x^2 + y^2 < 1, save a few GPU cycles ;)

    • @Rust_Rust_Rust
      @Rust_Rust_Rust 2 ปีที่แล้ว +18

      Yeah square both sides and you still get 1.

    • @rutvikpanchal5726
      @rutvikpanchal5726 2 ปีที่แล้ว +26

      Only if your radius is 1, does not work with radius != 1

    • @fmdj
      @fmdj 2 ปีที่แล้ว +94

      @@rutvikpanchal5726 well in that case you can square the radius instead of square-rooting the x^2 + y^2, this is beneficial cuz square (simple multiplication, one instruction) is way cheaper than square root computationally

    • @utkarshgupta4041
      @utkarshgupta4041 2 ปีที่แล้ว +7

      what if I tell you I have a circuit that can calculate square root in one CPU cycle.

    • @chicomferreira
      @chicomferreira 2 ปีที่แล้ว +5

      @@rutvikpanchal5726 you can just compare it with radius^2

  • @fari7s
    @fari7s 2 ปีที่แล้ว +137

    I learned about such a Soft and Round circle rendering technique, in a book: "The Book of Shaders". Really good book for beginners (and not only) will help you in shader coding and understanding.

    • @regbot4432
      @regbot4432 2 ปีที่แล้ว +4

      Thanks for recommendation

    • @fari7s
      @fari7s 2 ปีที่แล้ว +3

      @@regbot4432 Glad to help)

    • @gldev8191
      @gldev8191 2 ปีที่แล้ว +2

      nice, will add it to my library!

    • @Brahvim
      @Brahvim 2 ปีที่แล้ว +1

      Sadly the online version was incomplete...

    • @danifeldman8884
      @danifeldman8884 2 หลายเดือนก่อน +1

      Thank you very much, I have downloaded the book. Happy to find your comment. :)

  • @kalakxfif9473
    @kalakxfif9473 2 ปีที่แล้ว +24

    That's a smooth and soft tutorial

  • @zzedixx
    @zzedixx 2 ปีที่แล้ว +59

    A "non-filled in circle" is called a circle. A filled in one is called a disk (It's actually more complicated than that but that's the simple explanation)

    • @King0Mir
      @King0Mir 2 ปีที่แล้ว +7

      A useful vocab, but still one that requires you to define your terms at the beginning, so it doesn't save you much.

    • @DeGuerre
      @DeGuerre 2 ปีที่แล้ว +4

      ...and the difference of two discs is called an annulus.

    • @prashanthkumar0
      @prashanthkumar0 2 ปีที่แล้ว +1

      what about soft circle then?

    • @cogwheel42
      @cogwheel42 2 ปีที่แล้ว +2

      a non-filled-in circle you can actually _see_ would be an annulus

    • @AlFredo-sx2yy
      @AlFredo-sx2yy 2 ปีที่แล้ว +1

      what happened to the simple days of circle vs circumference

  • @DeGuerre
    @DeGuerre 2 ปีที่แล้ว +4

    Something that works even better than a static "fade" amount is to scale it depending on the fragment size. In OpenGL 3, this is surprisingly easy to compute by using derivatives:
    const float sqrt2 = sqrt(2.0);
    float fade = sqrt2 * length(vec2(dFdx(distance), dFdy(distance)));
    This produces a pixel-resolution fade which works even when the quad is distorted.
    If you want an even crisper, but still antialiased, edge, you can use a linear smoothstep (which I call "lerpstep"). It is essentially the convolution of step() with a box filter.
    float lerpstep(float edge, float delta, float x) {
    float edge0 = edge - delta;
    float edge1 = edge + delta;
    return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
    }
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    // etc etc
    float distance = length(uv);
    float fade = length(vec2(dFdx(distance), dFdy(distance)));
    float alpha = lerpstep(thickness, fade, distance) - lerpstep(1.0, fade, distance);
    // etc etc
    }

    • @bobsmithy3103
      @bobsmithy3103 2 ปีที่แล้ว +1

      Thanks for the code example! I never knew that dFdx and dFdy even existed before now. In case anyone was like myself and was quite confused about dFdx and dFdy, here's how I understand it:
      dFdx allows you to compare a variable of the current pixel being rendered to that same variable of the neighboring pixel to the left. Essentially the function returns the DIFFERENCE of a variable between two pixels that are horizontally right next to each other. This is useful because it tells us how much our variable changes per pixel which when rephrased, tells us how much we need to change our variable to get a pixel worth of width. dFdy is the same as dFdx except it compares pixels vertically instead of horizontally, so when a pixel is being rendered it'll look to the pixel above it to get the difference in their variable. Note this variable can be anything from user supplied varyings like uv coordinates, or variables like gl_PointCoord. Though you could supply a constant value like `1` to dFdx or dFdy but it would just return `0` as all pixels would just have the same value (as 1-1=0).
      Because we now know how much we need to change our variable to get a pixel worth of distance both horizontally and vertically, we can use it produce 1 pixel's worth of anti-aliasing which Pseudonym73 has shown above.

    • @DeGuerre
      @DeGuerre 2 ปีที่แล้ว +2

      @@bobsmithy3103 This is exactly right, except for one quibble: you should think of dFdx and dFdy not as differences, but as derivatives. They are indeed implemented as differences (which means they are not magic, in that they don't give you an analytic derivative), but semantically they are derivatives.
      These may be the most useful operators that nobody (except those who came to OpenGL shaders from RenderMan) seems to know about, because they give you the information you need for shaders to antialias themselves.

  • @FerrumMusicVideos
    @FerrumMusicVideos 2 ปีที่แล้ว +8

    As simple as a circle is, it took me a while to even get the concept of how to render one. Thanks for this video.

  • @mickeym.9721
    @mickeym.9721 2 ปีที่แล้ว +8

    Filled in “circle” = Disc
    “Circle” outline = Circle

  • @kebrus
    @kebrus 2 ปีที่แล้ว +3

    the smoothstep function has one draw back, if you increase or decrease the size of the circle you either get antialising again because the smoothstep threshold is to small or you get a blurry edge because the threshold is too big, a somewhat good alternative is to use the fwidth function to calculate the edge smoothing, since it uses derivatives they are "screen size" aware so it doesn't matter which size your circle is in the screen, the draw back is that it's a bit more expensive and derivatives uses 2x2 pixel blocks which in some shapes can be seen, it's not the case with circles tho
    not sure how derivatives work with shadertoy but the final code would be: distance / fwidth( distance )

  • @md2perpe
    @md2perpe 2 ปีที่แล้ว +8

    In mathematics, at least, the "outline of a circle" *is* the circle. A circle plus the region inside it is called a disk or a (2-dimensional) ball.

  • @HumanGamer
    @HumanGamer 2 ปีที่แล้ว +11

    I would be interested in a video where you implement it into the batch renderer. Please make it :P

    • @nicobugs
      @nicobugs 2 ปีที่แล้ว

      Yes please

  • @Altrue
    @Altrue 2 ปีที่แล้ว +10

    Throughout the whole video I was wondering how you were gonna make the edges smooth. I don't know if there are other, more efficient anti aliasing methods, but isn't it weird to have a anti aliasing function (=smoothstep) that depends on the number of pixels of the radius? Like, it you make the circle very small, you have to change the fade value, same if you make the circle very big.
    Maybe I don't have the right use cases in mind, but here's what I see:
    1- UI: If you use your shader to draw a circle in the UI, then at least you'll always control how big or how small it is, so that's easier. But you still have to manually adjust the fade for each size of circle you have in your UI, and each resolution the game supports. Otherwise, the edge will either look too jagged or too blurry sometimes.
    2- Gameplay: If you draw a circle in the 2D/3D world, the problems above are still relevant, but in addition to that, I suppose that the circle could change size dynamically due to gameplay events (distance to camera, growth/shrinking etc)
    So there seems to be missing, from this video, a way to make the fade value be proportional to the total screen resolution for each frame.

    • @unschlagbar2302
      @unschlagbar2302 13 วันที่ผ่านมา

      every value like the color, radios, border can be passed to the shader as a uniform buffer or a push constant. the video only show the fragment shader side but you can imagine that you can have as many rectangels as so want at any possition and the frag shader can draw a circle on every of them

  •  2 ปีที่แล้ว +10

    You could also use the derivative functions available in GLSL (such as fwidth) to make the smoothstep range one pixel in size, regardless of the scaling of the object or screen resolution. Would be pretty interesting to see that implemented!

  • @RadicDotkey
    @RadicDotkey 2 ปีที่แล้ว +17

    You should have used a linear interpolation for antialiasing instead of a smoothstep otherwise you get some weird two edged gamma "correction" I know as I compared both methods with Photoshop's antialiasing pixel by pixel. Additionally the fade variable needs to be calculated from texel size. When it's a constant you will get different smoothing for different circle sizes.

    • @CoDEmanX47
      @CoDEmanX47 2 ปีที่แล้ว +4

      Do you have a Shadertoy example of that?

    • @realedna
      @realedna 2 ปีที่แล้ว +3

      So you have to calculate, if a pixel is part of the circle and to what amount.
      That means, if a pixel is less than ~1 pixel away from the edge, then color it partially according to the amount of overlap.
      You could just use the floating point fraction from the distance (when it's

  • @NoodleFlame
    @NoodleFlame 2 ปีที่แล้ว +2

    It depends, I have two different ways. My first method uses triangles, the number of sectors is determined by the camera distance, increasing the closer it gets. The second method uses the Bresenham circle algorithm. I can use this to draw pixels directly to a framebuffer or via a batch renderer where every pixel (for outlines) or every row of pixels (for solid) is a seperate quad. I didn't really have any concerns with the number of quads/triangles I was drawing as my batch renderer can ouput 1.7 million with a single draw call at over 70fps on my laptop and I don't tend to draw circles all that often for pixel games.

  • @Zekronz
    @Zekronz 2 ปีที่แล้ว +14

    I recommend using fwidth over smoothstep for anti aliasing as it won't be resolution dependent.

    • @realedna
      @realedna 2 ปีที่แล้ว

      Partial derivatives of what function? A hard step?

  • @aaron6807
    @aaron6807 2 ปีที่แล้ว +1

    Your channel is highly underrated views wise. That said I like your videos and find them highly useful
    Thanks man

  • @zxuiji
    @zxuiji 2 ปีที่แล้ว +2

    9:37, I woulda put the x/y center at the top left of the normalised space, done normal caluations then just multiply the results against width and height normalised with the bigger have a smaller normalisation value, so 1 should be 1.0 and the bigger made to be smaller as a result of division, I think bigger divided by smaller would get the right value, this method ensures the dimensions are always as expected, as for x/y being in top left corner it makes it easier to multiply against position to get in right spot, only having to check if the position should be multiplied against positive or negative version of the axis

  • @slowfastdog9693
    @slowfastdog9693 2 ปีที่แล้ว

    I just found your channel and it's awesome to finally find some premium quality Aussie content that's actually interesting as Zenva didn't agree with my ADHD.

  • @danielsliberatingstructure6539
    @danielsliberatingstructure6539 2 ปีที่แล้ว +22

    I was wondering: regarding the thickness - wouldn’t you have to take into account the transformation applied (or the distance to the camera) within the shader function, so that a circle with a thin line (aka a donut of ‘tiny’ thickness) stays thin no matter the draw distance - or maybe even more relevant: the aliasing created by smoothstep() is working regardless of draw distance(? Proximity to the object ? Closeness to the camera?) . I guess I am throwing a lot different concepts together - my apologies for that - the last time I wrote code for an 3D engine is 15 years ago, I never worked with shaders, and I forgot about all the terminology and how different concepts play together.

    • @erich1394
      @erich1394 2 ปีที่แล้ว

      @The Cherno Brilliant tutorial - I'm an audio DSP programmer and it's quite wild to experience the same sort of geometric thought process but in higher dimensions. (Audio is 2D, time and amplitude).
      @Daniels Liberating Structures-Kanal - I have the same question as you, but for ellipses with a high fade value. I wanted to ask specifically what local variable can we use to figure out the transform applied to the shader? If we had access to the "aspect ratio" of the ellipsoid, we'd be able to easily compensate for this stretched-fade / stretched-thickness effect, but being a complete newbie to openGL, I know that this problem would probably require a good day of plinking around and I'd really like to hear a professional chime in on this!

    • @SirusStarTV
      @SirusStarTV 2 ปีที่แล้ว

      If you don't get transform matrix through Uniform and apply it to vertex shader then it would be just circle in 2D screen space.

    • @SimonBuchanNz
      @SimonBuchanNz 2 ปีที่แล้ว +1

      The correct approach to anti-alias an edge is to use the pixel width, which I believe you can get pretty easily in a shader with the derivative function on the UV (which just compares the passed value to what it is in neighboring pixels).

    • @DFPercush
      @DFPercush 2 ปีที่แล้ว

      Pretty sure that will just come out in the wash when you project UV coordinates into world space. The rasterizer will calculate how the distance and perspective (applied in the vertex shader) affects each pixel. The fragment shader is only working with a sample point, usually the center of the pixel, but it could be multiple points if multisample shading is enabled. If you need a flat, constant width circle, you can either omit the transformation matrix from the pipeline, or you could use a "look at" function to render the quad and point it straight at the camera.

  • @S41L0R
    @S41L0R 2 ปีที่แล้ว +3

    It'd be cool if Hazel had full curve support in-runtime. Think of all the animations and blending you could do with them!
    There would definitely be some challenges, but if you can do it efficiently and simply, it would be awesome.

  • @RenkoGSL
    @RenkoGSL 2 ปีที่แล้ว +2

    It was nice to see you avoid the branch call. And add fade to thickness. Good job Cherno! Keep up the good work!

    • @zoltankurti
      @zoltankurti 2 ปีที่แล้ว

      Does it avoid the branch call? Depends on how step is implemented.

  • @vladprusakov
    @vladprusakov 2 ปีที่แล้ว +2

    I need more shadertoys series! Thanks, Yan

  • @vikinggeorge7007
    @vikinggeorge7007 2 ปีที่แล้ว

    1m side square would produce a circle of 1m diameter. The 0.5m you're talking about is the radius. Just clarifying to make things easier to understand.

  • @maksymiliank5135
    @maksymiliank5135 ปีที่แล้ว +1

    you could also create a geometry shader which is going to take point primitive as an input and turn those points into quads and then render the circles that way. If you use this you can then define the color and radius of the circle as a parameter in the vertex buffer

  • @stefanarctic1966
    @stefanarctic1966 2 ปีที่แล้ว +3

    Yes I would be interested in a video of an implementation

  • @microcolonel
    @microcolonel 2 ปีที่แล้ว

    Love the videos man, they're great to send to beginners; make sure you get up and get your steps in; gotta pay attention when you're working from home long term.

  • @yassin_eldeeb
    @yassin_eldeeb 2 ปีที่แล้ว +2

    Thank you for the amazing tutorial, I now appreciate the abstraction done in some higher level languages for rendering graphics 😅

  • @Test-iv4pm
    @Test-iv4pm 2 ปีที่แล้ว +1

    I would love to see a shader series.

  • @quickstergamestutorialsgam3899
    @quickstergamestutorialsgam3899 2 ปีที่แล้ว +8

    I bet if you covered c++ 3D games, like not writing a whole 3D game engine, but just coding a game like you would do with your old java series. That would be great.

    • @human-ft3wk
      @human-ft3wk 2 ปีที่แล้ว

      I think he mentioned a game is coming up! But for the most part, it seems like he's interested in engines more than games.

    • @qvindicator
      @qvindicator 2 ปีที่แล้ว

      That would be amazingly helpful to watch. I hope he considers it

  • @KebunH
    @KebunH 2 ปีที่แล้ว +1

    I think to get consistent smoothness with smoothstep the step size should depend on the resolution, as the goal is to for example stretch the step over 2 pixels (in which the smooth step size would be 2 divided by the total amount of pixels)

  • @MrDimakoles
    @MrDimakoles 2 ปีที่แล้ว

    i like renderer topic the most, it's your speciality. keep it up please and good luck

  • @playerzero5388
    @playerzero5388 2 ปีที่แล้ว

    "Meet my cousin, Smooothstep. Some say he's a smooth kinda guy."

  • @antontheyeeter
    @antontheyeeter 2 ปีที่แล้ว +4

    Finally what i need

  • @AltamishM
    @AltamishM 2 ปีที่แล้ว +2

    If we smoothstep this way, aren't we then losing the fade where the outer edge of the circle touches the four sides of the canvas? Could look a little chopped off if the fade is large. Might be worth subtracting the fade from the distance.

  • @Mempler
    @Mempler 2 ปีที่แล้ว +2

    You missed an meme opportunity when you said "smooth soft circles"

  • @philippk736
    @philippk736 2 ปีที่แล้ว +1

    Just to clear up the nomenclature: A circle refers to the outer perimeter, the inside area of the circle is a disk.

    • @Destroyer19941995
      @Destroyer19941995 2 ปีที่แล้ว

      😬

    • @sebastianzander87
      @sebastianzander87 2 ปีที่แล้ว +1

      And the word Chemo was looking for earlier is a ring (i.e. a circle with a thickness, a flat donut so to speak) 😉

  • @filiformis
    @filiformis ปีที่แล้ว

    Google recommended me this video after watching Casey Muratori's video on rendering a circle. As if anything could top that.
    I mean I'm still going to watch this video and give it my engagement, obviously, but still.

  • @perfectionbox
    @perfectionbox 2 ปีที่แล้ว +1

    the video is... well rounded

  • @theoathman8188
    @theoathman8188 2 ปีที่แล้ว +1

    you can apply these techniques in SDF type rendering as well.

  • @Test-iv4pm
    @Test-iv4pm 2 ปีที่แล้ว +2

    There is a little twinkle in your eye each time you describe a circle as "soft"

  • @notarandom7
    @notarandom7 ปีที่แล้ว

    My Ray Caster: I'm 6 Parallel Universes ahead of you

  • @ADEPS.
    @ADEPS. 6 หลายเดือนก่อน

    I haven't even created a window yet. 10/10.

  • @joshuaalan7580
    @joshuaalan7580 2 ปีที่แล้ว

    When you pulled up the printed circle I was fully expecting you to go "...can't believe I wasted a sheet of paper on this"

  • @ebkdeviousd3392
    @ebkdeviousd3392 2 ปีที่แล้ว +1

    Thankyou for teaching me something this morning =)

  • @dave_s_vids
    @dave_s_vids 2 ปีที่แล้ว

    Really interesting, despite me having zero use for what you just showed us :D Thanks!

  • @LB767
    @LB767 2 ปีที่แล้ว

    Just as I needed to render a bunch of circles, excellent :D

  • @CoDEmanX47
    @CoDEmanX47 2 ปีที่แล้ว +1

    If the triangle count is important, then just use a single, large enough triangle per circle instead of a quad. I can't recall how to calculate the exact size, however.

    • @Erlisch1337
      @Erlisch1337 2 ปีที่แล้ว

      just put the circle on a texture for that quad...hehe....

  • @jlewwis1995
    @jlewwis1995 2 ปีที่แล้ว +1

    I haven't watched the video yet but my guess is for rendering a circle you want to just take a quad and render it as a circle with a shader taking the center of the quad as the center of the circle and comparing the distance of the UV from the center and if it's greater than the radius you render nothing and if it's less you render the circle

    • @jlewwis1995
      @jlewwis1995 2 ปีที่แล้ว

      Lol I was right after less than a minute 🤣

    • @ChrisM541
      @ChrisM541 2 ปีที่แล้ว

      @@jlewwis1995 I'm not sure you realise how both your posts read! "I haven't watched the video yet but" --> good grief !!

  • @fluffy537
    @fluffy537 ปีที่แล้ว +1

    Thanks Cherno, interesting video, but what if I want to draw a circle in 3D space, viewed from any angle? Your method seems to only work if you are drawing a circle in 2D space, viewed from above and with the circle in the centre of the screen.

  • @redox5373
    @redox5373 2 ปีที่แล้ว

    i was just wondering how to render circles, and my saviour came

  • @karelhofman9848
    @karelhofman9848 2 ปีที่แล้ว

    create video, another easy technic is to just draw a quad with a texture of a white circle on it. to color the circle just shade the texture and scale the quad to create an ellipse. the smooth shading isn't needed anymore if linear filtering is enabled. it is not possible to create donuts with this technic though.

  • @Bonfra04
    @Bonfra04 2 ปีที่แล้ว

    love this kind of video! can you make one about a way to fill a shape described by a series of point?

  • @robertmoats1890
    @robertmoats1890 ปีที่แล้ว

    Thanks for the great video! The first time I implemented an SDF circle, it was a piece of cake until I got to the point where I needed to define a falloff for smoothstep(). Technically, the thickness of a circle outline should be oriented so that the middle of the thickness falls exactly on the radius of the circle, right? So half thickness on both sides of the radius edge. But this means the quad needs to be expanded (in clip space) by thickness*0.5 + falloff in every direction. Since my quads were sized in world space, trying to figure out how much to push them outward for this using a clip-space distance was not very much fun. I think I spent around 3 days on it.

  • @DejaimeNeto
    @DejaimeNeto 2 ปีที่แล้ว +1

    I always wanted to render me some beautifully soft circles.

  • @zxuiji
    @zxuiji 2 ปีที่แล้ว

    Looking at that code make me think of lights, perhaps there's a cheat method of lighting objects by simply going over the entire rendered buffer with similar math

  • @jamesmnguyen
    @jamesmnguyen 2 ปีที่แล้ว

    Wow, young me was so naive. In the past, I always rendered 2d circles using a triangle fan. When I could've used a shader.

  • @fredg8328
    @fredg8328 2 ปีที่แล้ว

    To render a circle in a texture there are techniques like the Bresenham circle algorithm but it doesn't really apply to a shader as you treat the pixels independently. For antialiasing there a techniques like the Wu algorithm which is a simplified version of multi-sampling, but again i don't know if it would be really faster in a shader.

  • @AndrewHelgeCox
    @AndrewHelgeCox 2 ปีที่แล้ว

    02:00 you call it a circle. It's the filled-in shape that you need a different word for.

  • @rodion988
    @rodion988 2 ปีที่แล้ว

    I would call a "non-filled in circle":
    1. circle perimeter
    2. circle boundary
    3. circle outline

  • @perfectionbox
    @perfectionbox 2 ปีที่แล้ว +2

    Just draw a letter O from an SDF font (or a circle emoji)

    • @igorthelight
      @igorthelight 2 ปีที่แล้ว

      Good as a joke :-)
      But for those who would try it "for real" - make sure that your engine/framework supports font rendering in the first place.
      Not sure that speed will be great tho (rendering a letter vs rendering the circle)

  • @DFPercush
    @DFPercush 2 ปีที่แล้ว

    Cherno, you know how Unity optimizes sprites by "cutting off" the edges of the quad and tracing the outline? What if you do that here? Render a hollow octagon, or some n-gon, with a triangle strip topology, wide enough for the circle to lie within it. That would cut down on the number of fragments you have to calculate. I think there's a formula for the inner and outer radius of a regular polygon... somewhere lol

  • @FinaISpartan
    @FinaISpartan 2 ปีที่แล้ว +2

    It's not recommended to use length as it uses a square root. You can instead just make distance equal to 1 - dot(uv). The reason being you could've done 1 - sqrt(dot(uv)) = 1^2 - dot(uv) = 1 - dot(uv)

  • @tenpham1127
    @tenpham1127 2 ปีที่แล้ว

    In my exp, 5 degrees for each triangle is good enough. If you're lazy, leave it to the system by using MaskOpacity on a Rectangle - very flex.

  • @OutlawJackC
    @OutlawJackC 2 ปีที่แล้ว

    Just wanna point out, that pc looks gucci :)

  • @williankoessler5935
    @williankoessler5935 2 ปีที่แล้ว

    distance = (float)(distance < 1.0 && distance > innerCircle);
    Without inverting distance (or just invert the logic)

  • @flat9safety
    @flat9safety 2 ปีที่แล้ว

    @32:50 nice edit!

  • @NaokiWatanabe
    @NaokiWatanabe 2 ปีที่แล้ว

    "Since we have an absolute unit range.."
    Me: "Yeah, that range is an absolute unit.

  • @jouniosmala9921
    @jouniosmala9921 2 ปีที่แล้ว

    After looking at this code I start to understand why rendering 8M pixels 100 times per seconds often needs more than 10Tflops compute.

  • @videojeroki
    @videojeroki 2 ปีที่แล้ว

    Interesting topic. Since I would like to display points (millions of points from laser scanning) I'm wondering if I could display those points as small circles using shaders. To be fair, the points could also be represented as square, triangle etc with different size and colours.

  • @gusterugamer
    @gusterugamer 2 ปีที่แล้ว

    2:00 i think the non filled is a circle, and the fill one is a disk

  • @LimitedWard
    @LimitedWard 2 ปีที่แล้ว

    I ran into this EXACT issue the other day. For my 3D app, I wanted to add a circle around my mouse cursor similar to the paintbrush tool in photoshop, but I couldn't for the life of me figure out how to do it.

  • @DigitalViscosity
    @DigitalViscosity 9 หลายเดือนก่อน

    Couldn't you just write a function "bool isCirclePoint(vec2 c, float rad, vec2 pos) { return length(c - pos)

  • @Rene-uz3eb
    @Rene-uz3eb 2 ปีที่แล้ว

    This put me off that openGL primitives don't support discs. I decided to skip the fragment shader and use compute to render into a texture buffer instead. At least that way I can do whatever I want, without artificial bounding boxes that need to be rotated with the geometry or making it transparent just so the box doesn't render etc.

  • @ScoopexUs
    @ScoopexUs 2 ปีที่แล้ว

    Apple does not support GLSL, so the title is incorrect. If the Metal shader language is the same, then Apple stole it and then stopped supporting it, and Metal is "we're workin on it..." for years. Safari does not support WebGL or WebGPU. Apple offers no equivalent to Shadertoy.
    If you set the circle to fade out, you are interpolating instead of antialiasing. It's better if the texture is higher resolution and antialiasing is performed by the GPU in context. If you target 2D worlds and want to optimize texture size, it's easy to use Pythagoras' theorem with quadrants to calculate how large an area of each edge pixel is inside the radius.

  • @nitricswight
    @nitricswight 2 ปีที่แล้ว

    Ooh I want that t-shirt

  • @bruno.myrrha
    @bruno.myrrha 2 ปีที่แล้ว +1

    Those are the times that I understand that working within games industry is a no-go for me =( My math skills are so bad that I don't even understand how I have a simple job.

  • @peezieforestem5078
    @peezieforestem5078 2 ปีที่แล้ว +1

    One way to do this would be to transform the UVs to polar coordinates, it is useful if you're doing other stuff within those coordinates.
    Also, I personally do branchless "if"/"step" with metaprogramming, but that might be a bit too advanced.
    And of course the other comments mentioned that you do not need a square root if you're comparing to 1, but once again, this is an optimization technique and so I understand why you wouldn't mention it.

    • @Drillgon
      @Drillgon 2 ปีที่แล้ว

      Do you think the shader compiler might optimize the sqrt? It might be interesting to see the gpu assembly output.

    • @peezieforestem5078
      @peezieforestem5078 2 ปีที่แล้ว

      @@Drillgon it might, but we really need to see assembly output. Personally, I think, why take the chance if you can just guarantee this?

  • @phlfm
    @phlfm 2 ปีที่แล้ว

    "A non filled circle" ahh yes.. a ring?

  • @ebkdeviousd3392
    @ebkdeviousd3392 2 ปีที่แล้ว

    Is this what games remasterers are doing for old games etc this kind of similar shading to make things more smooth? So potentially if I wanted to and could see game code I could smoothstep every step they have to remaster circles wheels etc myself?

  • @rigbyb
    @rigbyb ปีที่แล้ว

    Amazing tutorial, thank you

  • @dasten123
    @dasten123 2 ปีที่แล้ว

    Rendering a circle is easy:
    - first you render a human head
    - then you erase some of the more detailed features
    - circle complete

    • @realedna
      @realedna 2 ปีที่แล้ว

      You will end up with a potato.

  • @brunomarques5258
    @brunomarques5258 2 ปีที่แล้ว +1

    Hi @thecherno, Do You have plans to port Hazel to directx 11 and/or 12?

  • @yakub548
    @yakub548 27 วันที่ผ่านมา

    You can clearly see how hard he's trying to not say "balls"

  • @GorBer84
    @GorBer84 2 ปีที่แล้ว

    Great videos thank you! could you please make videos about navigation mesh generation for AI and voxelization ?

  • @cadfoot568
    @cadfoot568 2 ปีที่แล้ว +1

    rip printer ink at the beginning

  • @realedna
    @realedna 2 ปีที่แล้ว

    Why so convoluted?
    This is my simpler and easier to understand version for an anti-aliased circle (not disc) with thickness, that is movable by mouse:
    float sdCircle( in vec2 p, in float r )
    {
    return length(p)-r;
    }
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
    float aa_dist = 0.01; // edge transition: fraction of y
    float r = 0.4; // radius: fraction of y
    float thks = 0.01; // thickness: 0 -> r
    vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y; // y from -1 to +1
    vec2 m = (2.0*iMouse.xy-iResolution.xy)/iResolution.y; // y from -1 to +1
    float d = sdCircle(p-m,r);
    // coloring
    vec3 bg = vec3(0.1,0.4,0.7);
    vec3 fg = vec3(1.0);
    vec3 col = mix( bg, fg, 1.0-smoothstep(0.0,aa_dist,abs(d)-thks));
    fragColor = vec4(col,1.0);
    }

    • @realedna
      @realedna 2 ปีที่แล้ว

      Or for a centered disc with a hole controllable via mouse:
      float sdCircle( in vec2 p, in float r )
      {
      return length(p)-r;
      }
      void mainImage( out vec4 fragColor, in vec2 fragCoord )
      {
      float aa_dist = 0.01; // edge transition: fraction of y
      float r = 0.6; // radius
      float thks = 0.01; // thickness: 0 -> r
      vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y; // y from -1 to +1
      float m = iMouse.y/iResolution.y; // from 0 to +1
      float d = sdCircle(p,r);
      // coloring
      vec3 bg = vec3(0.1,0.4,0.7);
      float thks_h = r*m/2.0; // half thickness
      vec3 col = mix( bg, vec3(1.0), 1.0-smoothstep(0.0,aa_dist,abs(d+thks_h)-thks_h));
      fragColor = vec4(col,1.0);
      }

  • @Test-iv4pm
    @Test-iv4pm 2 ปีที่แล้ว

    1:55 What if you didn't want a filled in circle? Also known as, in the industry, a "non-filled-in circle"

  • @liamandersson5462
    @liamandersson5462 2 ปีที่แล้ว

    How do you make it scaleable in GLSL? I have Matrices up and running, however it only scales the background of the "circle shader". Not the actual circle.

  • @King0Mir
    @King0Mir 2 ปีที่แล้ว

    One thing that immediately came to mind when you started showing the fade effect, is what about anti-aliasing? It seem like the purpose of your fade is actually to avoid anti-aliasing while still making it look somewhat good. Why not apply proper anti-aliasing instead?

    • @igorthelight
      @igorthelight 2 ปีที่แล้ว

      What form of an AA tho?
      You would have to compare the speed of different methods.

  • @watercat1248
    @watercat1248 2 ปีที่แล้ว

    Persnly If want to make I perfect circle 🔴 I will probably use i 2D image or texture on 3D plain

  • @joysaha3927
    @joysaha3927 2 ปีที่แล้ว

    I would love to see how to integrate this on batch renderer series. :)

  • @ymi_yugy3133
    @ymi_yugy3133 2 ปีที่แล้ว

    There was a paper about parallelizing Bresenham's circle rasterization algorithm. It's unclear though it's suitable for the gpu.

    • @DFPercush
      @DFPercush 2 ปีที่แล้ว

      The rasterizer in a GPU is kind of baked into the hardware, you can't really have a parametric function that chooses which pixels to sample. You could generate a point list of every pixel, perhaps with a compute shader. Not sure it would be any faster than this though. Listing every point is a lot of memory. You might get this one faster if you render over an actual mesh that doesn't process so many pixels.

    • @_lod
      @_lod 2 ปีที่แล้ว

      The gpu already does things in parallel.

    • @ymi_yugy3133
      @ymi_yugy3133 2 ปีที่แล้ว

      @@DFPercush The GPU rasterizer can only rasterize points, lines, triangles and maybe rectangles. So this algorithm would need to be implemented as a compute shader.
      I don't understand your concern about memory. Whether you use the final image as a render attachment or storage texture shouldn't make much difference in terms of memory size.

    • @ymi_yugy3133
      @ymi_yugy3133 2 ปีที่แล้ว

      @@_lod Yes, but the process shown in the video has a fair amount of overhead, because it has to run through the entire render pipeline, because the pixel shader is run for every sample.

    • @DFPercush
      @DFPercush 2 ปีที่แล้ว

      @@ymi_yugy3133 Memory access time is what I'm thinking about, more so than size. Not sure what kind of cache a GPU has or what it has to share it with. Actually a tessellation or geometry shader might be better because it can just stuff vertices into the rasterizer pipeline and not have to allocate a buffer at all.

  • @bernard3690
    @bernard3690 2 ปีที่แล้ว

    Greetings Kind Regards How the heck does your computer compute those shaded circles immediately upon change of your program or are you editing the video to make it appear so Thank You Kindly

  • @tristunalekzander5608
    @tristunalekzander5608 2 ปีที่แล้ว

    I would just use circle texture on a quad with transparent blending.

  • @KarimElHayawan
    @KarimElHayawan 2 ปีที่แล้ว

    Always helpful to remember that a circle isn't a disc.

  • @siman211
    @siman211 2 ปีที่แล้ว

    So i watch all the videos i try to code at the same time with you do a different version of that code and when i think that i learn something i just don't
    I try to do some problems on code wars and even the easy ones are to hard for me any advace?
    Sorry for my english

  • @ericmasson7462
    @ericmasson7462 2 ปีที่แล้ว

    thanks mate! I am down for a GL specific vid. cheers

  • @razorstone3088
    @razorstone3088 2 ปีที่แล้ว +1

    A circle that's not filled in.
    A Ring

    • @AkamiChannel
      @AkamiChannel 2 ปีที่แล้ว +1

      Technically I think it's just a circle. And the filled in one is a disc. But for colloquial terms, I think your way is better.

  • @retroryuu7254
    @retroryuu7254 2 ปีที่แล้ว

    Very well explained :D