Rendering a Sphere Using Ray Tracing! // Ray Tracing Series

แชร์
ฝัง
  • เผยแพร่เมื่อ 27 ก.ค. 2024
  • Visit brilliant.org/TheCherno to get started learning STEM for free, and the first 200 people will get 20% off their annual premium subscription. AMAZING place to learn all the math you'll need for this series!
    Support on Patreon ► / thecherno
    Discord (#raytracing-series) ► / discord
    Source code ► github.com/TheCherno/RayTracing
    🧭 FOLLOW ME
    Instagram ► / thecherno
    Twitter ► / thecherno
    Twitch ► / thecherno
    Learn C++ with my series ► • Welcome to C++
    📚 RESOURCES (in order of complexity)
    🟢 Ray Tracing in One Weekend series ► raytracing.github.io
    🟡 Scratch a Pixel ► scratchapixel.com
    🔴 Physically Based Rendering: From Theory to Implementation ► amzn.to/3y2bGK7
    💾 SOFTWARE you'll need installed to follow this series
    Visual Studio 2022 ► visualstudio.microsoft.com
    Git ► git-scm.com/downloads
    Vulkan SDK ► vulkan.lunarg.com
    Welcome to the exciting new Ray Tracing Series! Ray tracing is very common technique for generating photo-realistic digital imagery, which is exactly what we'll be doing in this series. Aside from learning all about ray tracing and the math to goes into it, as well as how to implement it, we'll also be focusing on performance and optimization in C++ to make our renderer as efficient as possible. We'll eventually switch to using the GPU instead of the CPU (using Vulkan) to run our ray tracing algorithms, as this will be much faster that using the CPU. This will also be a great introduction to leveraging the power of the GPU in the software you write. All of the code episode-by-episode will be released, and if you need help check out the #raytracing-series channel on my Discord server. I'm really looking forward to this series and I hope you are too! ❤️
    CHAPTERS
    0:00 - Intro
    1:15 - Creating a Renderer class
    12:13 - Structuring our code to work like a pixel/fragment shader
    21:00 - Rendering a sphere using our math work
    This video is sponsored by Brilliant.
    #RayTracing

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

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

    Hope you all enjoyed the video! Don't forget we have a Discord channel for this series (#raytracing-series), and a discussion thread there for each episode - go ahead and post your spheres there! discord.com/channels/349857236656324608/990217821021679636/990217929972924416
    If you need to brush up on your math, visit brilliant.org/TheCherno to get started learning STEM for free, and the first 200 people will get 20% off their annual premium subscription.

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

      ;)

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

      Great series Cherno, always wanted to do my own rendering
      Please make a series where u completely code a renderer basically render the current hazel
      Would love that

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

    Hope you are doing fine. Currently doing your C++ tutorial Series. You are the champ man!

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

      I definitely earned more money at work by watching and learning that series. It's really good

    • @user-dh8oi2mk4f
      @user-dh8oi2mk4f 2 ปีที่แล้ว +1

      @@zch7491 You do ray tracing at work?

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

    Really enjoying this series. Looking forward to the next video!

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

    You can press CTRL twice to enable / disable inline hints (those parameter things)

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

      I love you

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

    I never thought i would understrand this in-depth👏👏👏

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

    Loving this style, keep it up!

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

    Hey the cherno, great tutorial series 👍. I was wondering though / i cant remember if you said so in your introduction video, if you will just do the basic stuff like simple shadows and reflections (the stuff that everybody does and stops after that) or if you will include more complicated stuff like 3D models, global illumination and so on...

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

    Wow this was very cool. Also didn’t know about shadertoy. I’m going to have to try that out

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

    Awesome series so far. From the comments I can see programmers seem to think their idea is the better idea lol.
    Are you planning on tackling BVHs during this series? Since RT became popular due to the new consoles/PC GPUs being able to handle RT and begin implementation it would be cool to see what BVHs are, how they work, etc seeing as how, for now, everything gaming related is using BVHs.

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

      As a beginner programmer the comments are actually giving me confidence. When someone like him will still be given advice on how to improve his code, it makes me feel better about my code lol

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

      Many of "their ideas" are in fact better, but Cherno tries to go for early results and will probably introduce those changes later, insead of throwing everything at the viewers at the same time.
      Checking if the intersections are in front (t1 and t2 positive) is something you have to do if objects can be behind the camera. If you forget it, you get weird results each time some happen to be inside the "reversed" view cone. Really weird, like spheres moving "backwards" when animated, an where the lighting looks inverted. (Yes, I forgot that check, too.)
      Normalizing the light direction to length one is something you should definitely consider if there are spheres. If there are only planes and polygons, it's less useful, but it's a cheap operation, so little harm done if you always do it.

  • @Basel-ll8fj
    @Basel-ll8fj 2 ปีที่แล้ว +1

    amazing work 3>

  • @williamchurch8401
    @williamchurch8401 4 หลายเดือนก่อน

    I love that you are walking us through it step by step! I feel a blind man gifted sight. ❤

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

    I love your videos man, thanks

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

    Very cool series.

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

    I've never heard you say it but I think your a genius 😮😮

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

    Shouldn't we check for t1 and t2 if they are positive? If t is negative it means the ray is not hitting the sphere. It means that the ray would have hit the sphere if it was pointing in the opposite direction (ray = origin + t * direction). Wouldn't this mean that the sphere will be rendered if it is in the back of the camera as well? Also, that z from the ray direction vector shouldn't be calculated in order to get the FOV that we want instead of setting it to -1? I tried to go alone through the mats of the previous video and I got this formula: z = -1 / tan(fov / 2).

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

    I have never felt as smart as when I was able to render a warped circle on to my screen a few seconds earlier than the cherno

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

    It would be quite cool to replace the straight line math with null geodesics in some non euclidean spaces (might be a bit slow), could do gravitational lensing simulations etc

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

    Aye, early! :D Good and concise explanation, Cherno!

  •  2 ปีที่แล้ว

    i just spent my last week to study for my computer graphics final exam. i got an A, but what's better is i kinda understand now what you are talking about :D

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

    It's a good idea to normalize RayDirection. This way the term 'a' (which is glm::dot(RayDirection, RayDirection) will always be == 1.0

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

      True, however a dot product is much faster than normalizing, so the code I wrote will actually be (significantly) faster.

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

      Yeah, just checked on current version of series' repo. With normalization render takes ~2ms longer (10ms vs 8ms without norm)

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

    You should make an ep on triangle intersection and rendering and maybe even bring in lighting using multiple lights? OP series though +1

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

      That's one of the next few lessons. For now, he tried to keep it as simple as possible and merely generate a hit/miss map of a sphere. The next lesson will probably be a single light source, then reflection and refraction, then infinite planes and possibly triangles. Light sources will almost surely be the next topic, since they will make the sphere look like an actual sphere rather than a circle.

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

    17:44, would've used local copies of the width height, pre-converted to floats, 2 less conversions the cpu has to make every call, then also a pre-converted y value in it's loop so when entering the x loop the x value is the only one that need to be converted frequently

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

      Not only that. You can predivide 1 by width and height to save on having to do division each loop iteration. Just the fact that all variables are local to the function will encourage the compiler to put them in registers which can increase performance. I know the often repeated "premature optimization... blah blah" quote. But in my opinion there's gotta be some middle ground. Sure, micro-optimizations that mess up the readability of the code is one thing but small things like these shouldn't be frowned upon.

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

      On a release build, invariants are optimised out of the loop by compilers, and expressions that can be executed at compile time will most likely be executed.
      Ofc one need to confirm this by checking the output assembly.

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

      @@Legendarior As long as you already as them converted in local variables you won't need to check the asm since you've made sure there will be some time savings with the local variables alone, the only way to guarantee more at that point would be to craft the asm yourself which is not worth it for modern computers, maybe for PS1 etc but that's it.

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

      @@zxuiji yeah I agree, there is always this tradeoff between readability and handmade optimisations (because you can't really trust 100% the compiler)

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

      Many of these optimizations will be made by the compiler, some will be aded at a later stage by Cherno, but for now the focus is on features rather than best possible performance. For newcomers, the formulas are complicated enough as they are now.
      BTW, you save FAR more time computing one sphere/plane intersection per line; that allows you to eliminate spheres from X pixels as a time rather than one, and even if you can't eliminate a sphere, you can reduce the math from the 3d case to a simpler 2d case. That can save far more time than the optimizations a good compiler can do. You might spend 2% of the time eliminating ~75% of the spheres in a typical scene and saving 40% of the calculations for those which remain, which would save 83% of CPU time.

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

    you can press control twice to toggle the parameters

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

    Will u do this using a compute shader later on?

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

    Would love to see raytracing on the GPU. There aren't many tutorials out there on that

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

    It would be cool to fully model the camera lens instead of just this basic approach. But, that's something for the [far] future.

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

      cherno is referring a bit from Raytracing in a weekend series and in it they do explore depth of field and focal distances so yes im excited to see it as well

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

    Each ray is perpendicular to a pixel right? do we not account for rays which land on the pixel obliquely?

  • @user-nk9fx6zn2l
    @user-nk9fx6zn2l ปีที่แล้ว

    What theme do you use for Visual Studio?

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

    Might be easier to just start with vectors and arrive at results in the quadratic coefficients that come from dot products

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

    this felt to me like he was programming in ue5 for a moment lol

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

    How to enable this new feature which shows variable types in small box ?

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

    17:45 I was wondering if the GetWidth() method call will have any overhead because it is called many times per pixel. would it be better if we store it as a local variable?

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

      i think GetWidth() is getting called at each iteration for dynamic resizing of the render

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

    32:00 these "a"s and "b"s are a bit confusing

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

    The problem is not the Ray origin, but you subbed in 4.0f as radius in the quadradic, instead of r (0.5).

  • @ricardosaraviaarmaulia3009
    @ricardosaraviaarmaulia3009 5 หลายเดือนก่อน

    Hi, someone know why in my pc the render time is so bad? I have an RTX 4090 and intel i9 i think i should get a nice render time(i get doing the first part of the video 200 ms ). Thank you.

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

    I'm way way to stupid to comprehend this stuff. It's unreal how you do this stuff

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

      not true. It might take more time for you, but there's nothing incomprehensible about it that an average human cannot do. Just go very slowly over what The Cherno says, pausing if necessary, looking up unfamiliar terms, slowly familiarizing yourself with concepts if necessary. It might take a lot of time, but you will understand it if you put the honest hours in.

  • @mr.mirror1213
    @mr.mirror1213 2 ปีที่แล้ว

    LESS GOOO

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

    When implementing this, I realized that the new Image::Resize function removes the need for the Image object to be dynamically allocated. Changing the Image object (m_FinalImage) into a regular member object helps to simplify the code by removing multiple nullptr checks. GetFinalImage can simply return a const reference to the member.
    Also, implementing m_ImageData as a std::vector can additionally simplify the OnResize function without adding any overhead.

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

    Nice tutorial, however I am really new to Github , and in my project I can't use the Image->Resize() because the Walnut app in my template isn't up to date because I set it up a few weeks ago. I was wondering how I would go about getting the Walnut app up to date, I have done some searching but am struggling to find an answer. If anyone could help with this I would really appreciate it, forgive me if the way I worded the question is weird.

    • @user-ec4ev3nq8h
      @user-ec4ev3nq8h 2 ปีที่แล้ว

      just chang to the Walnut directory
      git checkout master
      git pull

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

      i have the same issue too. It seems the Walnut submodule is in "detached head" status. So i went to the RayTracing/Walnut folder and use "git checkout master" command. And it works for me

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

    wonder if that is an apartment or an office?

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

    Goodness, What colorscheme is this?

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

    Can't upload screenshots here, unfortunately, but here's my stab at the "homework":
    float discriminant = b * b - 4.0f * a * c;
    if (discriminant < 0.0f)
    {
    return 0xff000000;
    }
    float time1 = (-b - sqrtf(discriminant)) / (2.0f * a);
    float time2 = (-b + sqrtf(discriminant)) / (2.0f * a);
    float t = std::min(time1, time2); // Get the closer time, so the ray hitting the "front" of the sphere
    glm::vec3 hitPoint(rayOrigin + rayDirection * t); // origin + direction * time
    glm::vec3 normal(hitPoint - glm::vec3(0.0f, 0.0f, 0.0f)); // Will be more interesting once the sphere moves...
    normal = glm::normalize(normal);
    auto scalar = glm::dot(rayDirection, normal) * -1.0f; // Simple shading based on the dot product of the normal and the direction: gets brighter closer to parallel
    if (scalar < 0.0f)
    {
    scalar = 0.0f;
    }
    if (scalar > 1.0f)
    {
    scalar = 1.0f;
    }
    auto brightness = static_cast(scalar * 255.0f);
    return 0xff000000 | (brightness

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

    is there a particular reason behind the m_ prefix you're using, does it stand for anything?

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

    Can I do this using opengl?

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

    Normalising the Ray Direction will allow you to skip calculating "a" because the dot-product of a line to itself is, well, 1.0f

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

      Normalizing is (significantly) slower than a dot product.

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

      @@TheCherno ooo I didn't know that, thanks!

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

    Hi from brazil, actually worth use std::string in an Engine that use for indie games our need own string types like QString etc, or is bad to production and cross platform? sorry for english

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

    Finally we have use for a discriminant after school :)

  • @m96fa40
    @m96fa40 3 หลายเดือนก่อน

    I'm gonna save somebody's time here:
    Guys NEVER EVER write *`coord *= 2.0f - 1.0f;`* just trust me and don't, it will make the circle look stretched, if you did the same problem as I did and struggled to fix, just change it to *`coord = coord * 2.0f - 1.0f;`*

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

    6:41, rather than a jump statement I would use function pointers and initiatlise Resize something like m_createCB and then have m_createCB change the pointer to m_resizeCB after it first succeeds, likewise m_resizeCB could change it back if it removes the allocation/s etc

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

      That's what we call premature optimization.

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

      A function pointer is alot more expensive than a single if statement

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

      @@homelikebrick42 Not when to get to that if statement you have to use a function pointer anyways, rather you have to lookup the symbol, load the address, load the bytes, whereas a direct function pointer skips symbol lookup since it already has the address and it skips the if statement as the pointer only changes during initialisation

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

      @@zxuiji "symbol lookup" happens during linking, as previously mentioned this is just premature optimization

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

      @@ciekce No, not with function pointers as the linker can only record the addresses where it's told, function pointers start as NULL typically because they're set during runtime, not link time, if you think I'm on about the functions themselves then you need to change concept, here's an example of what I mean in C:
      typedef struct memory mem_t;
      typedef void* (*resize_cb)( mem_t *mem, size_t size );
      struct memory
      {
      size_t cap;
      void* ptr;
      resize_cb resizeCB;
      };
      extern mem_t const mem_t_defaults;
      ...
      void* create_memory( mem_t *mem, size_t cap )
      {
      (void)ptr;
      ...
      mem->resizeCB = resize_memory;
      return mem->ptr;
      }
      void *resize_memory( mem_t *mem, size_t cap )
      {
      ...
      mem->resizeCB = create_memory;
      return NULL;
      }
      mem_t const mem_t_defaults = { 0, NULL, create_memory };

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

    10:53, I would just have swappable pointers, something like:
    Image::SwapImages()
    {
    m_swapping = true;
    LockMutex( &(m_mutex) );
    ImageCfg *tmp = m_showImage;
    m_showImage = m_editImage;
    m_edit_Image = tmp;
    m_swapping = false;
    FreeMutex( &m_mutex );
    }
    That way can keep the memory that already have if it's big enough.

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

    clicked

  • @user-ph5cu2tr8d
    @user-ph5cu2tr8d 2 ปีที่แล้ว

    cool

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

    ;)

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

    You can turn off this thing by double clicking CTRL

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

    we must have an RTX card for this series? :(

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

      ;)

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

      No, rtx cards is to use nvidia's ray tracing application but here we are creating our own application so we don't need it and it can be done on any card.( Please correct me if I am wrong)

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

      @@tejasmaloor2507 You're right, Ray Tracing isn't something invented by nVidia, nVidia just made that their videocards do calculation really fast

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

      not really this can even be done in CPU, obviously speed will be affected by what device you are using

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

      @@roxxel8167 i understand, its really interesting to know why big company doesn't do those things in there engine's if this youTuber show it so easily, i only heard about crytech that implemented ray tracing in there engie and lumen in unreal engie but its no really a ray tracing, its just a fake and smart ray calculations that are really great 😅

  • @Mr.Dirkelz
    @Mr.Dirkelz 2 ปีที่แล้ว +3

    Will you ever use the rust programming language, it fixes a lot of C/C++ mistakes, and I would like a rust series with , because I am struggling translating c libraries like raylib to the raylib-bindings for rust, because of the borrowing system, otherwise I will just be switching to C, but I do not like it as much as rust and I have to relearn it because of the borrowing system, otherwise I will just be switching to C, but I do not like it as much as rust and I have to relearn it

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

      What mistakes

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

    please make a game engine code in java.

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

    2d/3d-dda on grid/quad/oct-tree is the most useful individual ray tracing algorithm (most robust), assuming all worst cases, all rays individually accelerated in the grid, think a very dense voxel fog or tree leaves

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

      you could multisample per pixel, or 4x screen size render the whole displayed image, resize resample down to the 1x image size

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

      you should have a separate render buffer, whatever dynamic resolution, then fit that to the final screen pixels

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

      set a value of supersampling (oversampling) resolution, like 1.25, 2, or 4, assume its same for x and y, compared to the window or screen image size

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

      0.5 render scaling would mean undersampling then fitting to screen

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

      ie, render 1080p then fit to 4K