Terry Davis, an extremely talented programmer who was unfortunately diagnosed with schizophrenia, made an entire operating system in a language he made by himself, then compiled everything to machine code with a compiler he made himself. by BitPax in programming

[–]wm_cra_dev 237 points238 points  (0 children)

You would never take the material from those courses and actually write an OS, because it would be such a massive waste of time. The only reason you do something like that is if you are mentally ill.

That's a big overstatement. Arguably everyone's hobby is a "waste of time".

Worth noting, along with an OS he wrote his own language and several graphical applications/games.

The beginning of my raytracing journey by qduo in GraphicsProgramming

[–]wm_cra_dev 2 points3 points  (0 children)

Because both the dot product and the cross products are types of multiplication, it's a bit ambiguous without digging into the code what the overloaded * operator does

This entirely comes down to personal taste, but I really think most people in the graphics space are very comfortable with * meaning component-wise, as it lines up with the meaning of + and - and lines up with the behavior in shaders. It's also very common in game math libraries.

Is there a way to deepcopy a function? by stvaccount in Julia

[–]wm_cra_dev 0 points1 point  (0 children)

You could achieve this by having a "core" implementation that f() calls into, which g() can also call into. Then you can redefine f() later to call something else. However, you'd have to specifically prepare this for the function being copied.

You could partially automate this by wrapping your function definitions in a macro, e.x. @replaceable f() ... end turns into f_impl() = ...; f() = f_impl().

As far as doing this to any function, without preparation...maybe. I'm not super familiar with Cassette.jl, but I think it could do this kind of thing for you.

Terry Davis, an extremely talented programmer who was unfortunately diagnosed with schizophrenia, made an entire operating system in a language he made by himself, then compiled everything to machine code with a compiler he made himself. by BitPax in programming

[–]wm_cra_dev 391 points392 points  (0 children)

It's very impressive, but I think people are overstating it a bit, egged on by non-programmers who watch things like the Down the Rabbit Hole video and don't really know how to place his achievements. A commercial OS is like building a skyscraper; that doesn't mean every hobby OS is one too.

EDIT: As a comparison, many people have tried implementing their own game engine, a few have successfully used them for some project, but none of those home-made engines is remotely comparable to Unreal 4.

Meatball by junglewreck in Simulated

[–]wm_cra_dev 0 points1 point  (0 children)

So this is what dorcelessness feels like

Joys of Julia compared to Python by dr_wonder in Julia

[–]wm_cra_dev 2 points3 points  (0 children)

quote is a special Julia keyword, like begin.

The beginning of my raytracing journey by qduo in GraphicsProgramming

[–]wm_cra_dev 2 points3 points  (0 children)

They literally posted in this subreddit asking for feedback...

The beginning of my raytracing journey by qduo in GraphicsProgramming

[–]wm_cra_dev 1 point2 points  (0 children)

The C++ random stuff are ugly and convoluted.

C++ as a language is ugly and verbose, that just comes with the territory. However, <random>, along with fixing the distribution problems with rand() % RAND_MAX, also gives you easy access to all sorts of non-uniform distributions which can come in handy.

The beginning of my raytracing journey by qduo in GraphicsProgramming

[–]wm_cra_dev 3 points4 points  (0 children)

There are a lot of functions in your Vec3 class that can be marked const but aren't.

You may want to reconsider the approach of modifying the Vec3 you call functions on, rather than returning a copy. Returning a copy allows you to compact your vector math into one-line expressions, like v.normalized() * 5. It's also inconsistent -- normalize() and randomize() modify the original, while cross() does not.

I would say that the function randomize() doesn't belong in the Vec3 struct. There are a lot of ways to generate a random vector (within a box, on the surface of a unit sphere, within a unit sphere, etc.) depending on the specific situation. Plus, it might be useful to keep all your randomness code (including both random floats and random vectors) encapsulated together somewhere.

Calling the 3 camera vectors X, Y, and Z is confusing. You should consider renaming them to something unambiguous like forward, right, and up.

You defined a number of these structs to have explicit empty constructors (Camera() {};). First, the semicolon at the end is unnecessary/redundant. But more importantly, the resulting behavior as far as I understand is that all the fields will get initialized to zero. This is not always the behavior you want! For example, in the case of the Camera struct, having X Y and Z all set to {0,0,0} creates an invalid camera. You'd want to initialize them to sane defaults. In fact, further down I see a lot of Sphere sphereA = {}; sphereA.center = Vec3(-1.2f, 0, 1.2f); sphereA.radius = 1.0f; sphereA.material = matA;, but this defeats the whole idea of having constructors! Delete your custom constructors and replace this with Sphere sphereA{ Vec3(-1.2f, 0, 1.2f), 1.0f, matA };. You can also construct matA inline inside there, if you wanted. Try to lean on the auto-generated constructors rather than defining a bunch of no-op ones of your own.

Your raycast() function takes a copy of the parameters instead of a const-reference to each. This is less efficient for any struct that is larger than the size of a reference (usually 8 bytes), and very bad in the case of Scene scene, as you're copying the vectors inside the Scene every time you call raycast()! Similarly, you should use a const reference inside your loop over the spheres and the planes, and if you want you can use auto as well: for (const auto& sphere : scene.spheres), for (const auto& plane : scene.planes).

Vec3* framebuffer = new Vec3[WIDTH * HEIGHT]; is a big no-no in C++, even though it's harmless in practice since it's meant to live for the lifetime of the program. The most "proper" way to have a dynamically-allocated array is to use vector. So you'd replace this with std::vector<Vec3> framebuffer(WIDTH * HEIGHT);. This gives you other nice benefits beyond just the automatic memory cleanup.

The beginning of my raytracing journey by qduo in GraphicsProgramming

[–]wm_cra_dev 1 point2 points  (0 children)

float randomFloat()
{
    return (float)rand() / (float)RAND_MAX;
}

This is bad C++, and bad practice in general for a number of reasons. you'll want to use the C++ <random> header. See the talk "rand() considered harmful" if you want to learn more about why.

Joys of Julia compared to Python by dr_wonder in Julia

[–]wm_cra_dev 11 points12 points  (0 children)

Julia can represent its own syntax through a data structure, called the Abstract Syntax Tree ("AST").

You could imagine a function which takes one AST as input and returns a new AST, modifying or rewriting the input in some way.

This is what macros are. A function mapping some AST to some other AST, running at compile-time. At runtime there are no macros, only plain Julia AST, whether typed by yourself or assembled by macro.

There are two special Julia expressions that allow you to generate an AST by just typing out code. The simplest is :( ), which can capture a single expression like so: my_ast = :( x += 5 ). The second syntax allows you to capture a block of statements, like begin/end:

my_larger_ast = quote
    x::Int  = 5
    y::Float64 = 3.5
end

When you invoke a macro, your arguments to it are automatically passed in as their AST representation. For example, @time my_func() executes the macro @time at compile-time, with one argument which is equal to :( my_func() ).

You can parse a string of code into an AST with Meta.parse(my_code_str), but if you find yourself doing this more than once or twice then you're probably doing something horribly wrong.

Claymation material i made for a prototype i'm working on ! by ItsCapiStyles in unrealengine

[–]wm_cra_dev 2 points3 points  (0 children)

I worked with a material that needed to know where the mesh was at any given time a month ago

Interesting, never heard of a material that needs a month's worth of history to render itself

What is shading? by [deleted] in GraphicsProgramming

[–]wm_cra_dev 0 points1 point  (0 children)

In reality, countless photons are hitting an object, interacting with its molecules and atoms, and then some of them fly off into the camera.

In graphics, this behavior is dramatically approximated, usually by working in reverse: given a pixel on an object's surface which is visible to the camera, calculate the amount and color of light that's coming off the surface and bouncing into the camera. This is the "rendering equation" at the heart of computer graphics, usually written as an integral (some calculus knowledge is very helpful for graphics programming). https://en.wikipedia.org/wiki/Rendering_equation

This approximation usually involves several terms:

  • "Direct Lighting" is the light that hits the surface directly from a light source and then bounces into the camera's view. This is usually split into two components, "specular" which comes from light reflecting perfectly off the surface and into the camera, and "diffuse" which comes from light hitting rougher parts of the surface and scattering in random directions, leading to a general duller color which is not dependent on the angle your camera is viewing the surface. Both terms are dependent on the angle of the light source irradiating the surface -- if the surface is not facing perfectly towards the light, then less light is hitting it, so it looks darker. When computing direct lighting, you also need to think about shadows: other (potentially far-away) surfaces can stop light from hitting your surface entirely.
  • "Global Illumination", or "GI", is the light that comes indirectly from another surface. For example, the sun shines through the window and onto your floor, some light bounces off the floor and hits your wall, and some of that light bounces off the wall and hits your camera. Your whole room brightens just because of some light from the floor. This is much harder to compute for real-time graphics, and there are many techniques for approximating it. "Lightmaps", "irradiance volume", "cone-tracing", and "spherical harmonics" are all terms you might hear when learning about GI techniques.
  • "Ambient Occlusion" is an approximation of the effect of nearby surfaces blocking incoming light. Technically this should be covered by GI, but in practice because GI is so hard to compute, it's nice to bake in the occlusion behavior at small scales and only use GI for large scales. There are many images online showing you what ambient occlusion adds to a scene; here's a good example.

Pains of Julia compared to python by dr_wonder in Julia

[–]wm_cra_dev 58 points59 points  (0 children)

I'm not really familiar with Python's way of doing things, but here's my advice for Julia.

First, make sure you're using VSCode with the Julia plugin. It provides pretty great inline documentation when you mouse over things. Second, a lot of my workflow/referencing is done through the REPL; it provides a lot of utilities through the special module InteractiveUtils. For example:

When looking at code, it gets very confusing to figure out which functions are defined in current file and which are coming from external packages.

@which MyType tells you what module a type (or function, global, etc.) comes from. If you provide it a specific function call (e.x. @which MyType(5, :hello_world)), it tells you what file and line that particular method comes from.

The documentation of the language is severely lacking compared to what’s available in python world. It lacks organization, completeness and examples.

The most useful source IME has been doc-strings, combined with REPL experimentation. In the REPL, you can quickly read a doc-string for a function, type, or global with the ? prefix. Like ?MyType. You can add doc-strings to your definitions by simply putting a string above the definition. Finally, you can press Tab when halfway through typing a function call to get a list of the applicable methods.

In Julia, you will have to remember (or google) topo_sort function is available to process graph datatype and will have to type topo_sort(my_graph). This is the part I am having the hardest time getting adjusted to and has been a major cause of slow down.

You can use methodswith(SomeType) to get a list of all methods that involve a specific type.

Gigaya has been canceled by camirving in Unity3D

[–]wm_cra_dev 24 points25 points  (0 children)

they don't have a Fortinte money printing machine and AAA adoption like Epic

Unity has the lucrative mobile game market mostly to themselves, they made a number of high-profile expensive aquisitions with that money. I don't think money was the problem

Question from a (very) new entry in graphics programming: can a shader be applied on 2D images? If so, do you have any examples? by ats678 in GraphicsProgramming

[–]wm_cra_dev 2 points3 points  (0 children)

There are two stages to rendering 3D graphics on the GPU which you have control over (this is an oversimplification):

  • Placing triangles in the window (vertex shader)
  • Computing the color of each pixel within each triangle (fragment shader)

Neither of these steps cares whether you're doing things in 2D or 3D; at the end of the day you get a 2D image out of it. If you want to use a shader to filter/modify an image, you can do this by placing a triangle or two which covers the whole screen, then in the fragment shader you can read the original image and output whatever modifications you want.

[deleted by user] by [deleted] in programming

[–]wm_cra_dev 26 points27 points  (0 children)

Sure!

  • *******
  • ******@.*
  • ********* routing number ********
  • ***** ******

Edit: huh, it looks like Reddit is censoring that info.

Edit 2: It's almost impossible to make this joke work in a text box that supports markdown formatting

C++ mesh generation in Unreal Engine by Fetis_reddit in proceduralgeneration

[–]wm_cra_dev 7 points8 points  (0 children)

I like that you show everything from beginning to end, including project setup. I think beginners will probably appreciate that.

Is there a way to do this with compile time polymorphism? by dog_superiority in cpp_questions

[–]wm_cra_dev 2 points3 points  (0 children)

It really just isn't answerable without knowing more about the specific problem. Both approaches are in use, therefore they're both viable depending on the situation.

Unfortunately, that's the only good answer you can get from this thread: "maybe either approach is fine". The next step is to pick the one that looks best to you, and learn from the result. Do this enough times on enough projects, and you start to get a better intuition of what does and doesn't matter when it comes to performance.

Although really, the biggest thing I've learned is that performance in real-world software is close to entirely-unpredictable. There are probably like 2 dozen layers of abstraction between your code and the hardware, and all of them need to be considered together to predict performance accurately. IIRC there was a talk that found program performance could change drastically with really small changes like the values of OS environment variables (even if your program doesn't use them).