How many times did you spot the cat? 🧐 Also you can try everything Brilliant has to offer-free-for a full 30 days, visit brilliant.org/TheCherno . You’ll also get 20% off an annual premium subscription!
another reason for the struct. Fetching data only once and stuffing as much as you can into a single cache line. "I like that it's not forced into OOP design for the sake of it" 20 minutes later "If I did it myself I would make it all OOP" Old habits die hard.
I think it depends oop is very efficient for writing applications with different components and reusing them. But you don't want to overdo it, always prefer composition instead of inheritance and try to have your classes as immuatable as possible and limits to the maximum modification of objects outside of their own classes : object should handle themselves. Mixing with functionnal is also a good idea because of immuatability. Making module for utility makes sense it avoid the verbosity of oop. And honestly it also depends on what langage you use, certains are better in other aspects than other
The moment I saw the code, I immediately thought: Class, RAII, Destructor. Which is what he ended up doing. I won't pretend I'm a c++ expert. But I tend to use simple functions which mostly gather information for initializing objects. I did some c code in the past, and once I fully embraced OOP in c++, I never looked back. How miserable things were. OOP and RAII. I love it. But I don't work for a large programming company. It's mostly solo stuff. So I might lack exposure to other code. Why I like watching his videos.
@@Cinarbayramictheres the idea of const as a promise. Essentially any time you create a function you const all inputs that you won't change. This means you can more easily understand how functions may impact data just by looking at the function def as const inputs won't change.
@@Cinarbayramici also found const to be completely useless concept that mostly obfuscates the code. I know what people say about const but i have never had any bug due to modifying something I shouldn't modify.
Honestly very good code for what it does. Bad code is unnecessarily complicated code, with useless abstractions, obscure one liners and single character variable names
About to send him the sidescrolling action-platformer I made when I was a teenager and didn't know what classes, interfaces, or lists were. The entire game takes place in a single update function with several hundred nested if statements. Every item and enemy is its own set of variables. It's made in Macromedia Flash MX. AlexIsCool321, you think bad code is your ally? I was born in it, *molded* by it.
I remember I did the same type of stuff with minecraft plugins when I was first learning, before java I only did batch and scratch, where in scratch that's kind of how I did everything, as scratch has no objects and I never really knew how to use lists appropriately. I was effectively doing everything with just variables and functions until I learned to use lists to make cooldowns, and then later learned how to properly use classes.
Maybe the code you said worst code made by 10 years old kid. When I was a kid, I made a ray tracing, and when I look back to the code when I'm an adult, I don't judge the code, I'm, just proud of my childhood.
I’m getting a feeling that Cherno is self reporting with this one. This is 100% the first raytracer he made on an old usb stick he found while cleaning the garage.
Writing C++ with a functional style can be magical, too. I think as Cherno pointed out in previous videos, sometimes makese sense to have functions over classes
I understand what you mean but "functional" typically doesn't mean "mostly uses free functions". Instead it means code that uses higher-order functions.
@failgun higher order, yes. And an OOP minded might fall into the trap of using invariance, objects, and state. When instead a function doing a simple data transformation is all that is required
@@thewhitefalcon8539 they're not the same. procedural programming is a paradigm in which you structure your code as a series of control flow steps that operate on variables and bundle common step sequences into procedures (functions). functional programming is a paradigm in which you structure your code as compositions of functions. There's no control flow or variables -- you typically don't use any kinds of loops in FP, but instead write your programs recursively or as combinations of higher order functions like map, filter, fold, zip and join among others.
Also gripe about "code quality": It's very much scale dependent, and also dependent on the skills of the maintainers. Like the primary metric of code quality would be how quickly can you add a feature without any side effects, or how quickly you can onboard a new dev to make said changes. When you have a sub 1k line code base, almost nothing can be considered "bad". I have a few ~6k line files and those I would call bad code as it's the entire program in a single file and it starts to take a considerable amount of time just jumping around looking for specific things that you forgot the exact names of. You could make it "good code" by just splitting it up into different folders and files to compartmentalize what all of the different features/functions do, but that takes effort and I just never care enough to do it as I don't spend much time changing things these days.
It's funny how you've done like 20 of these code reviews or whatever but you never seem to get much past their entrypoints lol... why not do a code review of AlmondCore?
The worst code I've ever seen was some React and NodeJS code at a previous employer. It was the worst example of over-engineering ever. Everything was so overly complex and difficult to do. Just changing a simple text label was complicated. I even argued with the tech lead about it more than once. I guess he thought the more complicated he made things , the smarter he felt as a developer. I think also it was his way of securing his job. By making the code super complicated, no one really understood it except him. But the code was very buggy, as you would expect, and just painful to work with. I eventually left after a few months.
I just wanna say, I've been learning C++ more productively. Watching these videos are seriously amazing, especially the tutorials. I don't wanna sound like those idiotic bot comments, but seriously, thank you.
lol, I've been trying to teach myself C++/C#, on and off, for about 30 years. I'm sure I've written the worst code you've ever seen hundreds of times. Thanks for the channel.
I am sort of glad I was able to come up with a similar solution to improve his code, I was definitely coding like this a few years ago, global variables, singletons everywhere...
I actually used the same GetDC trick for an image cat tool to view images in cmd. I no longer use it because I use the new windows terminal and it didn't work there.
@@user-sl6gn1ss8p I kinda wish that the new pseudoconsole subsystem would not eat arbitrary escape codes, so I could install a terminal that supports sixel, iterm2 or the kitty image protocol or some cool graphics like tektronix or regis. In linux you can just invent an escape code and implement support for it in a thirdparty terminal. You want audio escape codes, sure?, You want escape codes for app specific drag n drop, why not? you want escape code for tooltips/multiple fonts/popups/vsync/custom chraracters and icpns/...? I would have many bad ideas...
I agree that OO shouldn't be the only solution but rather a tool in the box, but in the case of a game or game engine, I feel like an object that separates out the functional bits of the program makes sense, especially when you consider that it makes it easier to run more than one at a time with ease. As for implementations of mathematical algorithms, I'd like to see some of the individual steps broken out into full-fledged functions marked as constexpr. However, I do agree on using a three piece vector to represent the data.
"I didn't identify my member functions". Hungarian notation, one of the most pointless programming styles ever invented, particularly for strongly typed languages and especially C++ which allows you to create your variables where they are used. Plus it's 2024, every bit of information encoded into your complicated and confusing prefix is available from the IDE.
One thing that is bothering me, and (I think) hasn't been mentioned, is how in SphereIntersect t0 and t1 are calculated for every pixel even though they are declared only in the scope of the function and not returned. So for every frame we have two operations with square roots which are fairly expensive performance-wise. In a regular raytracer we'd still calculate t0 and t1 for good reasons (which are mentioned in this video), but in this specific case there's no reason to.
I appreciate that you don't get hung up on minor style things and focus on functionality. It's something that always bothers me way too much and I'm trying to stop 😂
he couldve also just implemented a vector multiplication function that takes to vectors to offload part of the math going on here. and if your really bothered with performance make it constexpr, static inline, or even a define do while 0 construct... one thing i dont think you did pick on is that the person has done all that math to calculate the points of intersection and then not do anything with them?!
The code is too boring to bother with. I wrote more complex programs on a TRS-80 with 4 KiB RAM in 1977, within days of using BASIC for the first time, when I was fifteen years old.
Well, I am a systems engineer so I really do have the worst code full of typos and no comments and duplicates and unused variables or obsolete functions... Unnecessary design patterns and non useful logs. I have them all. 😅
How did you miss the fact that he calculates t0 and t1 in sphereIntersection and then never uses them at all? float t0 = ... float t1 = ... return true; He could have just calculated the discriminant of the quadratic equation and returned whether it was >= 0.
6:08 I felt this :D I'm a university student and I started learning code from C. Then I studied OOP and now I literally cannot think about code without classes and objects. I am now learning C++ and I have some problems in using other paradigms (maybe because even outside of coding, my mind often structure concepts in a OOP way, don't know if it makes sense). Does someone have any tips or resources (preferably videos) to learn other ways to code, especially in C++?
It is not the topic but a few about premake: it looks like comfortable but it can't link static libs((( I tried it to build SFML-project with static libraries, and it returned me mistakes with wrong runtime between project and libs, while CMake linked this project successfully, and I couldn't find the solution (but the dynamic libs were linked and worked). Premake needs revision
That was fun. I agree that that was not too bad. I have seen some HORRIBLE code!! I have asp code that I have to work with from time to time that is absolutely terrible!!!
Technically they never really did create a temporary, even though they should have. But using the pre-increment/decrement operators is always preferable just to ensure that you're not relying on the optimiser to do its job. (And also you don't have to switch operators when using a more complex type where construction/destruction might have side effects that break optimisation.)
THANK YOU. I had to scroll this far down the comment section to see that I was not the only one that noticed that. How could everyone miss it?!? This is the biggest flaw of all, IMO. People obsessed with y = y + 1 and then not noticing this unnecessary computation with unused variables. He would need these to determine the closest point of intersection if this was an actual ray tracer.
ammm quick question, i leaned (or am learning) how to code when i got 18 -19 before that it was just maths and science. now those who had done coding since they were without beards. and i had seen this pattern that after 2 decades since they started everyone becomes a greek dev (now i am 21 and hasn't beeen that much in this ape territory. i did know a bunch of languages but nothing to the degree to call myself a good one (i don't personally think i am a good programmer, other apes differ) anyway so well now i ma think of finally getting on and creating a project (give me tips like how do i actually start it- i might think of this feature and that , no i want to know how its done thanks) edit : > gawd dammmmmit, since when did youtube start to support markdown
Honestly i write my c++ like C. Ive moving to odin though as its C but nicer and from my tests performs better than c++. Best thing is no make/cmake and libraries are just drag and drop to vendor folder that comes with odin
@@TU7OV The other day I was using ChatGPT to ask it a simple question about unit testing Rust. It wrote some code, made up an API, and said you can do this but also told me it had made up the API call, (which is new because it usually doesn't own up to that sort of thing). When I said, "How can I do this when the API doesn't exist?". It said, "My appologies, you can't use an API that doesn't exist". Thanks ChatGPT. Excellent work.
@6:50 I only learned OOP about 3.500000001 years ago, but once I finally wrapped my head around it, I went absolutely balls-to-the-wall with it, and yeah, for at least 2 of those years: "everything had to be a class." Since then, I think I've begun to find a good balance with it. Many things I create are still classes and objects, because it just makes organizational sense in the right places, but I have gone back to a more "functional" form with other things. Usually, I find, that once I've started writing some convoluted inheritance nonsense to solve a problem, I have to take a beat and ask myself if this problem is best solved with OOP. Lots of times OOP really is the best option, but plenty of times, it's really is not.
Is there really a problem with global variables in a namespace? It fixes the biggest problem with them, and in my opinion it's perfectly fine to use them over passing them around everywhere. Like for window width and height. If something needs to be modified all over then it should be global, in a name space. It's not like people have a problem with global functions or static functions in classes, but they're essentially the same thing, if you think about it. Personally, as well as using namespaces and global variables (in namespaces) far more than I used to, I have also started using structs far more often and classes far less (structs as in just data with no functions). And even with classes I have started using public variables instead of getters and setters unless the data needs more context to update or needs bounds checking or something like that (and even then I'd try to solve the problem with structs, constructors and overloading before setters). I have slowly developed this style as I've programmed longer. I used to do everything 'correctly' but honestly at least for me this style of coding is a lot nicer to look at, a lot less likely to cause mistakes, and a lot easier for me to reason about. Like for running, theoretically you would want to kill the program from anywhere for any reason, so it makes sense for it to me modifiable as a variable. It is something you want to change from main, or maybe also within a class, etc. It's pointless having two whole functions to do the job of one variable. Then when you make such variables private you have to start passing context around everywhere when you realise that actually everywhere needs it. If you find you're passing an object around to every class and every function because you need something in it - make it global - you're far more likely to make a mistake and have _global_ state decynced if you try to pretend something that is global isn't. It is one piece of advice that I don't really agree with anymore. Personally global variables are fine. If they need to be modified and they are global state - then fine, it's called global state for a reason. If they should not be modifiable but need to be read from many places make them a global constant - again you're fine. The only problem is namespace pollution, and more importantly: Making things global variables that shouldn't be (e.g. things that are possible to be incorrect values but need to be correct always. Like a global int that must be between 0 and 10 but can be set to higher values). In this case you can't really check a global variable. However in this case even just make a class/struct with the correct bounds checking (static functions or better constructors), and make an of that global, and modify it like: ranged_int = ranged_int(4); or something. The constructor will then check the bounds or panic with an error state of sorts (or use a default value). So in my opinion global variables are underrated and needlessly feared. As long as namespace scope exists anyway. Without it, yeah, no globals.
Static functions in glasses get scoped to the class though. IMO it's mostly about scoping and namespaces. As stuff was in a Ray namespace here I would normally say it's fine. That said, you are assuming you will only ever have one window if you do it this way. I like to think about the ability to do pop ups, or to split tabs into new windows in a lot of applications, so depending on what you are doing that isn't a great assumption. Due to that I think you should have a window class that you can create instances of. And if you have multiple windows you may want to delete the main one at which point I would prefer to at least pull the variable into a window.cpp file and cache it in some collection of windows. Though I may extern the collection as a global exposed via the header... but given the issues around externing I would probably return the collection by reference from a function instead. At least, if this project was ever meant to be made into a more extensive raytracer or application. As a proof of concept which this seems to be, this is fine.
using global variables is bad style of programming. global variables lye in bss, usually in completely different memory page, and computer needs to load that entire page each time you want to access them. local variables are on stack, they are in cache, they are faster to access.
Name-clashing, which is the problem namespaces solve, is probably the most insignificant issue with global variables (and equally applies to functions and types). It is certainly not "the biggest problem with them". The biggest problem with them is the introduction of global mutable state, that is, they facilitate hiding pre-conditions and side-effects. That said, global constants are different, they are just configuration parameters baked into the code (as opposed to loaded at run-time), that may be appropriate (e.g., default capacity of a container), or maybe not (e.g., URL of the game server). Global variables that hold loaded configs are OK too, since they're essentially just global constants after the loading phase. Code that uses global mutable state is hard to test in isolation or requires a lot of setting up the conditions for a test. It's hard to hermetically duplicate, i.e., have multiple instances of the same class or functionality. It can make forensic analysis very difficult, that is, reproducing an issue seen in the wild (or Q/A) from logged data, because, with global state, you can end up in a situation where nothing short of a full core dump will allow you to repro a bug. Finally, global state can often make determinism really hard to achieve because your overall code is path-dependent (past events may have an influence on the current behavior), and this can quickly render things like continuous integration test pipelines and static analysis completely unusable due to inconsistent behavior between runs. Global variables have on one of these weird up-and-down learning curves for people. Usually, when you learn your ABCs, you get told it's bad style and they should be avoided, but the reasons often appear kind of pedantic. Then, as you work on small scale projects, you "learn" to love them because they don't really do much harm at that scale and kind of short-cut a lot of annoying design issues (as you've described). And finally, you get a real job, at scale, with hundreds of colleagues and millions of lines of code to deal with, and then you discover that there isn't a single piece of global mutable state that isn't causing headaches on a day-to-day basis. Then, you wish global variables had never been invented.
@@mike200017 This is true. I was looking mostly at a small project context. Globals are much more annoying in large projects. Still not too bad if there are only a few accesses, but if there are lots of accesses where they might be mutated, it's a nightmare to track down.
How many times did you spot the cat? 🧐
Also you can try everything Brilliant has to offer-free-for a full 30 days, visit brilliant.org/TheCherno . You’ll also get 20% off an annual premium subscription!
wasn’t ready for class Cat : public Animal 🤣🤣
Wait, she had other cameos, besides the "class Cat : public Animal" one at 6:50? 😳
kitty spotted at 22:36!
Is this... a competition?
It is now 😂
You have not seen what I have seen.
Such things have been done. For one example look up "harder drives".
@@steffenbendel6031 you have not seen what I have written
"We have such sights to show you" - Hellriser, Cube firmware division.
another reason for the struct. Fetching data only once and stuffing as much as you can into a single cache line.
"I like that it's not forced into OOP design for the sake of it" 20 minutes later "If I did it myself I would make it all OOP" Old habits die hard.
Or best practices die hard.
I think it depends oop is very efficient for writing applications with different components and reusing them. But you don't want to overdo it, always prefer composition instead of inheritance and try to have your classes as immuatable as possible and limits to the maximum modification of objects outside of their own classes : object should handle themselves. Mixing with functionnal is also a good idea because of immuatability. Making module for utility makes sense it avoid the verbosity of oop. And honestly it also depends on what langage you use, certains are better in other aspects than other
The moment I saw the code, I immediately thought: Class, RAII, Destructor. Which is what he ended up doing.
I won't pretend I'm a c++ expert. But I tend to use simple functions which mostly gather information for initializing objects.
I did some c code in the past, and once I fully embraced OOP in c++, I never looked back. How miserable things were. OOP and RAII. I love it.
But I don't work for a large programming company. It's mostly solo stuff. So I might lack exposure to other code. Why I like watching his videos.
7:00 Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function. - John Carmack
But method is a function right?
@@AdityaSharma-zn7hj A method is a function attached to an object. All methods are functions, but not vice versa.
@@thenonsequitur thanks
In c++ it's "member function", c++ doesn't have "methods", but everyone knows what it means.. just being pedantic for no reason
@@n00blamer I didn't know that about C++, but C++ is an oddball in that respect. They are called "methods" in most OOP languages.
Maybe challenge that guy and send my code ?🤔
Well. I probobly can make it worse......
@@matsv201 You have to do it unintentionally otherwise it's no fun
@w花b well. Im a really bad programer. So that is really not an issue
I have some really horrific code, but it's in JS.
😂
There's a distinct lack of const in this code
Well i dont use const too, i dont know why people use it can you explain
@@Cinarbayramictheres the idea of const as a promise. Essentially any time you create a function you const all inputs that you won't change. This means you can more easily understand how functions may impact data just by looking at the function def as const inputs won't change.
@@Cinarbayramicthere are many benefits of using constants in c++. You should google it and read up on them.
@@Cinarbayramici also found const to be completely useless concept that mostly obfuscates the code. I know what people say about const but i have never had any bug due to modifying something I shouldn't modify.
@@nan0s500 It happens fairly rarely for your own code it's mostly for others using your code like on a team or in a library
Honestly very good code for what it does. Bad code is unnecessarily complicated code, with useless abstractions, obscure one liners and single character variable names
Well there were some of the latter. ^^
@irrelevant_noob true 😅 but it's found very commonly in this scenario
About to send him the sidescrolling action-platformer I made when I was a teenager and didn't know what classes, interfaces, or lists were.
The entire game takes place in a single update function with several hundred nested if statements. Every item and enemy is its own set of variables.
It's made in Macromedia Flash MX. AlexIsCool321, you think bad code is your ally? I was born in it, *molded* by it.
I remember I did the same type of stuff with minecraft plugins when I was first learning, before java I only did batch and scratch, where in scratch that's kind of how I did everything, as scratch has no objects and I never really knew how to use lists appropriately. I was effectively doing everything with just variables and functions until I learned to use lists to make cooldowns, and then later learned how to properly use classes.
Maybe the code you said worst code made by 10 years old kid. When I was a kid, I made a ray tracing, and when I look back to the code when I'm an adult, I don't judge the code, I'm, just proud of my childhood.
I’m getting a feeling that Cherno is self reporting with this one. This is 100% the first raytracer he made on an old usb stick he found while cleaning the garage.
Writing C++ with a functional style can be magical, too. I think as Cherno pointed out in previous videos, sometimes makese sense to have functions over classes
aka procedural
I understand what you mean but "functional" typically doesn't mean "mostly uses free functions". Instead it means code that uses higher-order functions.
@failgun higher order, yes. And an OOP minded might fall into the trap of using invariance, objects, and state. When instead a function doing a simple data transformation is all that is required
@@thewhitefalcon8539 they're not the same.
procedural programming is a paradigm in which you structure your code as a series of control flow steps that operate on variables and bundle common step sequences into procedures (functions).
functional programming is a paradigm in which you structure your code as compositions of functions. There's no control flow or variables -- you typically don't use any kinds of loops in FP, but instead write your programs recursively or as combinations of higher order functions like map, filter, fold, zip and join among others.
@@thewhitefalcon8539 unless you're using Pascal
t0 and t1 are never actually used !
yea xd as the code is one can just return discriminant >= 0; but probably the author left it unfinished and t0/t1 were meant to be used
@@twujstary1129 yeah those are usually intersection points, when ray intersects sphere there can be 0, 1 or 2.
Also gripe about "code quality": It's very much scale dependent, and also dependent on the skills of the maintainers.
Like the primary metric of code quality would be how quickly can you add a feature without any side effects, or how quickly you can onboard a new dev to make said changes.
When you have a sub 1k line code base, almost nothing can be considered "bad".
I have a few ~6k line files and those I would call bad code as it's the entire program in a single file and it starts to take a considerable amount of time just jumping around looking for specific things that you forgot the exact names of. You could make it "good code" by just splitting it up into different folders and files to compartmentalize what all of the different features/functions do, but that takes effort and I just never care enough to do it as I don't spend much time changing things these days.
Impossible. The worst code is always the code I wrote yesterday, followed closely by the code I wrote a year ago.
Hello, Cherno. Could you please make videos about modern CPP features such as modules, constinit, reflection (?), std::println(), views, etc...
just watch the jason turner cpp weekly daily vids
"class Cat : public Animal" 🤣
y = y + 1 was crazy.
Not if you are as old as I am and learned the fundamentals of programming on a Sinclair Spectrum.
Code quality is very scale dependent. At a small enough scale, no code that works can really be "bad".
On higher scale, any code that works, isn't definitely bad.
It's funny how you've done like 20 of these code reviews or whatever but you never seem to get much past their entrypoints lol... why not do a code review of AlmondCore?
The worst code I've ever seen was some React and NodeJS code at a previous employer. It was the worst example of over-engineering ever. Everything was so overly complex and difficult to do. Just changing a simple text label was complicated. I even argued with the tech lead about it more than once. I guess he thought the more complicated he made things , the smarter he felt as a developer. I think also it was his way of securing his job. By making the code super complicated, no one really understood it except him. But the code was very buggy, as you would expect, and just painful to work with. I eventually left after a few months.
I just wanna say, I've been learning C++ more productively. Watching these videos are seriously amazing, especially the tutorials. I don't wanna sound like those idiotic bot comments, but seriously, thank you.
I have never seen someone refer to dx, dy, and dz as direction... usually it's delta, though I guess direction is technically correct.
lol, I've been trying to teach myself C++/C#, on and off, for about 30 years. I'm sure I've written the worst code you've ever seen hundreds of times. Thanks for the channel.
These review vids are great! Thx for taking the time and effort to share them! 😀
yeah he's amazing at stretching 100loc into a 25min video
This has so much instant fired energy in it you gotta love it. How common is it these days for people to do `using namespace Everything`?
I am sort of glad I was able to come up with a similar solution to improve his code, I was definitely coding like this a few years ago, global variables, singletons everywhere...
The reason to define variables outside of main is to have effectively immutable global state.
I actually used the same GetDC trick for an image cat tool to view images in cmd. I no longer use it because I use the new windows terminal and it didn't work there.
I never knew you could do this, sounds fun
@@user-sl6gn1ss8p I kinda wish that the new pseudoconsole subsystem would not eat arbitrary escape codes, so I could install a terminal that supports sixel, iterm2 or the kitty image protocol or some cool graphics like tektronix or regis. In linux you can just invent an escape code and implement support for it in a thirdparty terminal. You want audio escape codes, sure?, You want escape codes for app specific drag n drop, why not? you want escape code for tooltips/multiple fonts/popups/vsync/custom chraracters and icpns/...? I would have many bad ideas...
@@theevilcottonball Yeah, it feels like that's what they should be for
That transition to the sponsor was very smooth
I agree that OO shouldn't be the only solution but rather a tool in the box, but in the case of a game or game engine, I feel like an object that separates out the functional bits of the program makes sense, especially when you consider that it makes it easier to run more than one at a time with ease. As for implementations of mathematical algorithms, I'd like to see some of the individual steps broken out into full-fledged functions marked as constexpr. However, I do agree on using a three piece vector to represent the data.
Any code you write becomes the worst code ever written when you come back tonit later
"I didn't identify my member functions". Hungarian notation, one of the most pointless programming styles ever invented, particularly for strongly typed languages and especially C++ which allows you to create your variables where they are used. Plus it's 2024, every bit of information encoded into your complicated and confusing prefix is available from the IDE.
Phew, thought he'd got some of my code at first ...
Imagine thinking this is the worst code you've ever seen. My code is at least 1 billion times worse than this.
One thing that is bothering me, and (I think) hasn't been mentioned, is how in SphereIntersect t0 and t1 are calculated for every pixel even though they are declared only in the scope of the function and not returned. So for every frame we have two operations with square roots which are fairly expensive performance-wise. In a regular raytracer we'd still calculate t0 and t1 for good reasons (which are mentioned in this video), but in this specific case there's no reason to.
I appreciate that you don't get hung up on minor style things and focus on functionality. It's something that always bothers me way too much and I'm trying to stop 😂
If that's the worst code you've ever seen, then my code would literally melt you into your chair.
The math code is bad because all it is is written out vector dot products that should be extracted into a method in Vector3
he couldve also just implemented a vector multiplication function that takes to vectors to offload part of the math going on here. and if your really bothered with performance make it constexpr, static inline, or even a define do while 0 construct...
one thing i dont think you did pick on is that the person has done all that math to calculate the points of intersection and then not do anything with them?!
C can use classes...
just put function pointers in the struct and pass the struct with a pointer named this :P
Function pointers in a struct for no reason are bad for performance.
Just use plain functions that take a pointer to the instance struct.
@@simonmaracine4721+1
classes aren't just function pointer containers. they have headers, vtable for inheritance...
@@doodocina u can kinda implement VTables in C, but i agree it's a pain. If you are going to do reimplement OOP, just use C++
@@doodocinainheritance is not a fundamental part of object oriented programming, it is an addition
So C is an OOP language
Oh, I could send the worst calculator ever that I wrote. I'd probably win this competition for the worst code
my minesweeper implementation would win that competition
Not the worst code ever. Not enough code to even qualify for the worst code.
All the worst code I have seen is proprietary. X_X
I don't know if its the worst code you've ever seen and I'm not about to stick around for 20 mins to find out, I prefer less bait titles
Thanks for letting us know
The code is too boring to bother with. I wrote more complex programs on a TRS-80 with 4 KiB RAM in 1977, within days of using BASIC for the first time, when I was fifteen years old.
No where close to the worst code I have ever seen. I've written worse code than that. Granted, it was almost 50 years ago when I was in high school.
At least he made something, better than me 😅
hey i have question, do you check other languages than c++? like c, rust, java etc
It is zoomit
Can someone remind me of the name of the application he's using for drawing stuff/taking notes on the screen?
End(); // "I don't think this even gets called 🙂🙂🙂🙂🙂
I give him credit... he does have a hell of a good sense of humor!!!
Well, I am a systems engineer so I really do have the worst code full of typos and no comments and duplicates and unused variables or obsolete functions... Unnecessary design patterns and non useful logs.
I have them all. 😅
If that's the worst code you've ever seen. You haven't looked hard enough
6:50 оливка jumpscare
How did you miss the fact that he calculates t0 and t1 in sphereIntersection and then never uses them at all?
float t0 = ...
float t1 = ...
return true;
He could have just calculated the discriminant of the quadratic equation and returned whether it was >= 0.
I was pretty sure my code made it out in the wild when I read the title
when everything is a class, its awesome. love classes
quite interesting video, liked it
6:08 I felt this :D
I'm a university student and I started learning code from C. Then I studied OOP and now I literally cannot think about code without classes and objects. I am now learning C++ and I have some problems in using other paradigms (maybe because even outside of coding, my mind often structure concepts in a OOP way, don't know if it makes sense).
Does someone have any tips or resources (preferably videos) to learn other ways to code, especially in C++?
Not the worst C++ code i have seen by any stretch, i see my own code daily
Did you really not notice that this person is using a *console window* for *graphics output*, as a cheap way to not have to make an actual window?!
he did notice. It's just not _that_ bad
how I can run metrix calculations on gpu ?
It is not the topic but a few about premake:
it looks like comfortable but it can't link static libs((( I tried it to build SFML-project with static libraries, and it returned me mistakes with wrong runtime between project and libs, while CMake linked this project successfully, and I couldn't find the solution (but the dynamic libs were linked and worked). Premake needs revision
That was fun. I agree that that was not too bad. I have seen some HORRIBLE code!! I have asp code that I have to work with from time to time that is absolutely terrible!!!
please make video like OOP vs Data oriented in c++
y++?!?!?! Wait, your telling me that modern compilers don't waste temporary doing that anymore and I can stop writing ++y? :)
Technically they never really did create a temporary, even though they should have. But using the pre-increment/decrement operators is always preferable just to ensure that you're not relying on the optimiser to do its job. (And also you don't have to switch operators when using a more complex type where construction/destruction might have side effects that break optimisation.)
Actually it would be an interesting video, at least for me, to see on how to make this multiplatform
Putting the opening brace on the same line and then a completely blank line after it is so cringe.
How do you navigate so quickly?!
16:05 You underestimate the failure of the American education system
No matter how bad your code is, mine's worse 😅
He did not get the point, that there is not point calculating intersection points, if you do not use the points.
THANK YOU. I had to scroll this far down the comment section to see that I was not the only one that noticed that. How could everyone miss it?!? This is the biggest flaw of all, IMO. People obsessed with y = y + 1 and then not noticing this unnecessary computation with unused variables. He would need these to determine the closest point of intersection if this was an actual ray tracer.
It is not as bad if you compare it with source code of Unity or any google project.
What happened to the raytracing tutorial series? D:
Is anyone going to mention the fact this that isn't ray tracing?????????? this is just normal rendering......
it is ray tracing. It traces rays to render the image. Normal rendering would be rasterizing triangles.
12:05 y = y + 1 is wild... Time to do y -= -1 for my next project.
y = y % 2 ? (y + 2) & -2 : y | 1;
headophilles
0:09 This would've been the funniest segue into a sponsorship from that anti-balding company that everyone was sponsored by a while ago
You mean Keeps?
@CoolModderJaydonX Yeah that was it
You can't convince me he din't ask chatGPT to give him a code for a really bad ray tracer after seeing that "all ready"
Nah, the "sence" is more indicative of ESL.
@@irrelevant_noobwhy not both?
Worst code you've ever seen? Hold my 🍺 😅
"Running where is it, that is sus" - why is everything you say is so epic... it would take A CHERNO to solve this riddle.
Pre-Increment vs. Post-Increment Operators in For loops preference??
I disagree. You haven't seen my code.
No, I can write the worsest code. Worsestes ever.
🤔edit: pretty great review and recommendations 👍
Where is the RayTracing series... :c
ammm quick question, i leaned (or am learning) how to code when i got 18 -19 before that it was just maths and science. now those who had done coding since they were without beards. and i had seen this pattern that after 2 decades since they started everyone becomes a greek dev (now i am 21 and hasn't beeen that much in this ape territory. i did know a bunch of languages but nothing to the degree to call myself a good one (i don't personally think i am a good programmer, other apes differ) anyway so well now i ma think of finally getting on and creating a project (give me tips like how do i actually start it- i might think of this feature and that , no i want to know how its done thanks)
edit :
> gawd dammmmmit, since when did youtube start to support markdown
*since* _forever,_ as far as I know. But it's a very limited markdown.
16:16 he doesn't use intersection points anywhere else
There's way bigger fishes in the sea cherno
Post your code and we will roast it
Honestly i write my c++ like C.
Ive moving to odin though as its C but nicer and from my tests performs better than c++. Best thing is no make/cmake and libraries are just drag and drop to vendor folder that comes with odin
I would like see Cherno asking chat-GPT to write some cpp code and then review it
That'd be boring, ChatGPT likes to make up APIs that don't exist
@@TU7OV The other day I was using ChatGPT to ask it a simple question about unit testing Rust. It wrote some code, made up an API, and said you can do this but also told me it had made up the API call, (which is new because it usually doesn't own up to that sort of thing). When I said, "How can I do this when the API doesn't exist?". It said, "My appologies, you can't use an API that doesn't exist". Thanks ChatGPT. Excellent work.
You should review undertale code tbh😂😂
is this the best code i have ever seen?
@6:50 I only learned OOP about 3.500000001 years ago, but once I finally wrapped my head around it, I went absolutely balls-to-the-wall with it, and yeah, for at least 2 of those years: "everything had to be a class."
Since then, I think I've begun to find a good balance with it. Many things I create are still classes and objects, because it just makes organizational sense in the right places, but I have gone back to a more "functional" form with other things. Usually, I find, that once I've started writing some convoluted inheritance nonsense to solve a problem, I have to take a beat and ask myself if this problem is best solved with OOP. Lots of times OOP really is the best option, but plenty of times, it's really is not.
Is it possible to send you some code for auditing?? )))
Does anyone the theme cherno is using?
That transition in to the Brilliant plug was SEAMLESS 😂
Is there really a problem with global variables in a namespace? It fixes the biggest problem with them, and in my opinion it's perfectly fine to use them over passing them around everywhere. Like for window width and height. If something needs to be modified all over then it should be global, in a name space.
It's not like people have a problem with global functions or static functions in classes, but they're essentially the same thing, if you think about it.
Personally, as well as using namespaces and global variables (in namespaces) far more than I used to, I have also started using structs far more often and classes far less (structs as in just data with no functions). And even with classes I have started using public variables instead of getters and setters unless the data needs more context to update or needs bounds checking or something like that (and even then I'd try to solve the problem with structs, constructors and overloading before setters). I have slowly developed this style as I've programmed longer. I used to do everything 'correctly' but honestly at least for me this style of coding is a lot nicer to look at, a lot less likely to cause mistakes, and a lot easier for me to reason about.
Like for running, theoretically you would want to kill the program from anywhere for any reason, so it makes sense for it to me modifiable as a variable. It is something you want to change from main, or maybe also within a class, etc. It's pointless having two whole functions to do the job of one variable. Then when you make such variables private you have to start passing context around everywhere when you realise that actually everywhere needs it. If you find you're passing an object around to every class and every function because you need something in it - make it global - you're far more likely to make a mistake and have _global_ state decynced if you try to pretend something that is global isn't.
It is one piece of advice that I don't really agree with anymore. Personally global variables are fine. If they need to be modified and they are global state - then fine, it's called global state for a reason. If they should not be modifiable but need to be read from many places make them a global constant - again you're fine.
The only problem is namespace pollution, and more importantly: Making things global variables that shouldn't be (e.g. things that are possible to be incorrect values but need to be correct always. Like a global int that must be between 0 and 10 but can be set to higher values). In this case you can't really check a global variable. However in this case even just make a class/struct with the correct bounds checking (static functions or better constructors), and make an of that global, and modify it like: ranged_int = ranged_int(4); or something. The constructor will then check the bounds or panic with an error state of sorts (or use a default value).
So in my opinion global variables are underrated and needlessly feared. As long as namespace scope exists anyway. Without it, yeah, no globals.
Static functions in glasses get scoped to the class though. IMO it's mostly about scoping and namespaces. As stuff was in a Ray namespace here I would normally say it's fine.
That said, you are assuming you will only ever have one window if you do it this way. I like to think about the ability to do pop ups, or to split tabs into new windows in a lot of applications, so depending on what you are doing that isn't a great assumption. Due to that I think you should have a window class that you can create instances of. And if you have multiple windows you may want to delete the main one at which point I would prefer to at least pull the variable into a window.cpp file and cache it in some collection of windows. Though I may extern the collection as a global exposed via the header... but given the issues around externing I would probably return the collection by reference from a function instead. At least, if this project was ever meant to be made into a more extensive raytracer or application. As a proof of concept which this seems to be, this is fine.
using global variables is bad style of programming. global variables lye in bss, usually in completely different memory page, and computer needs to load that entire page each time you want to access them.
local variables are on stack, they are in cache, they are faster to access.
Name-clashing, which is the problem namespaces solve, is probably the most insignificant issue with global variables (and equally applies to functions and types). It is certainly not "the biggest problem with them". The biggest problem with them is the introduction of global mutable state, that is, they facilitate hiding pre-conditions and side-effects. That said, global constants are different, they are just configuration parameters baked into the code (as opposed to loaded at run-time), that may be appropriate (e.g., default capacity of a container), or maybe not (e.g., URL of the game server). Global variables that hold loaded configs are OK too, since they're essentially just global constants after the loading phase.
Code that uses global mutable state is hard to test in isolation or requires a lot of setting up the conditions for a test. It's hard to hermetically duplicate, i.e., have multiple instances of the same class or functionality. It can make forensic analysis very difficult, that is, reproducing an issue seen in the wild (or Q/A) from logged data, because, with global state, you can end up in a situation where nothing short of a full core dump will allow you to repro a bug. Finally, global state can often make determinism really hard to achieve because your overall code is path-dependent (past events may have an influence on the current behavior), and this can quickly render things like continuous integration test pipelines and static analysis completely unusable due to inconsistent behavior between runs.
Global variables have on one of these weird up-and-down learning curves for people. Usually, when you learn your ABCs, you get told it's bad style and they should be avoided, but the reasons often appear kind of pedantic. Then, as you work on small scale projects, you "learn" to love them because they don't really do much harm at that scale and kind of short-cut a lot of annoying design issues (as you've described). And finally, you get a real job, at scale, with hundreds of colleagues and millions of lines of code to deal with, and then you discover that there isn't a single piece of global mutable state that isn't causing headaches on a day-to-day basis. Then, you wish global variables had never been invented.
@@mike200017 This is true. I was looking mostly at a small project context. Globals are much more annoying in large projects. Still not too bad if there are only a few accesses, but if there are lots of accesses where they might be mutated, it's a nightmare to track down.
Thread safety 💀
Not working on windows 11 :/
2:05 SOAB
Pre or post increment differentiates between basic and advanced C++ developers.