# Hodgman

Moderator

15007

• #### Days Won

27

Hodgman had the most liked content!

52301 Excellent

## Personal Information

• Website
• Role
Game Designer
Programmer
Technical Artist
Technical Director
• Interests
Programming

## Social

@BrookeHodgman
• Github
hodgman

## Recent Profile Visitors

92348 profile views

1. ## Do you need a degree on top of good experience?

Yep. That's enough. Stop trolling threads, please, Fulcrum. As a last note: As well as technical skills and degrees, interpersonal skills are also a key to employment. Failing to realise that you are being obnoxious can be quite damaging to your career.
2. ## Do you need a degree on top of good experience?

Saying it over and over again for 5 pages, not just once, but in many different threads, constantly derailing other people's discussions... Is borderline trolling. Please stop trolling our forum.
3. ## "Nice" tweakable S-function

This thread is a great resource! At one point in time, I wanted a tweakable S-curve that could have a linear section in the middle and ended up with this mess: float SCurve( float x, float white = 10, float shoulder = 3, float slope = 1.5; ) { float invWhite = 1/((slope/shoulder)*(white-shoulder*2)); float one_on_shoulder = 1/shoulder; float slope_on_shoulder = slope/shoulder; float white_minus_two_shoulder = white-shoulder*2; float white_minus_shoulder = white-shoulder; x = min(x,white); float a = pow( abs(x*one_on_shoulder), slope ); float b = slope_on_shoulder*(x-shoulder)+1; float c = slope_on_shoulder*white_minus_two_shoulder + 2 - pow(abs((white-x)*one_on_shoulder), slope); return x < shoulder ? a : (x > white_minus_shoulder ? c : b); } The maximum x value is called "white" because I was using it for tonemapping HDR images http://www.wolframalpha.com/input/?i=plot+piecewise[{+{abs(x%2F3)^1.5,+x+<+3},+{(1.5%2F3)*(10-2*3)+%2B+2+-+abs((10-x)%2F3)^1.5,+x+>+10-3},+{(1.5%2F3)*(x-3)%2B1,+3<%3Dx<%3D10-3}+}],+x+%3D+0+to+10 http://www.wolframalpha.com/input/?i=plot+piecewise[{+{abs(x%2F5)^4,+x+<+5},+{(4%2F5)*(10-2*5)+%2B+2+-+abs((10-x)%2F5)^4,+x+>+10-5}+}],+x+%3D+0+to+10 Left: white = 10, slope = 1.5, shoulder = 3 (x<3 is the bottom shoulder, 3<x<7 is linear, 7<x is the top shoulder) Right: white = 10, slope = 4, shoulder = 5 (x<5 is the bottom shoulder, 5<x is the top shoulder)  https://www.desmos.com/calculator/p7emj3bmmq
4. ## R32G32B32 texture format cannot be sampled in pixel shader?

https://msdn.microsoft.com/en-us/library/windows/desktop/ff471325(v=vs.85).aspx R32G32B32 is only optionally supported for filtering - you need to query the driver for support before using it with a non-point sampler.
5. ## Using a variable in multithreaded environment - volatile, mutex or what?

Yep. But not JUST the compiler. Some CPUs will reorder your instructions at runtime (e.g. Intel), some will reorder memory reads and writes (Intel in certain situations), some will do both! Low level ASM/binary instructions are actually basically a high level byte code these days, and modern CPUs will take that instruction stream and dynamically compile it into another set of internal instructions... Optimising on the fly So, you do some work, make sure that the work is actually completed and visible to other CPU cores, then write the boolean. The lock will take care of that platform-specific CPU ordering, cache flushing, RAM visibility nonsense, with compile-time hints, and runtime instructions, if necessary on your current platform. In this particular situation, you could also just use a std::atomic instead of a lock+boolean -- they have functions that let you write a value after also performing a memory-fence operation. Due to CPUs reordering things, thread 2 might read the work and then the boolean, or thread 1 might write the boolean and then write the work. Either of those situations would cause thread 2 to process old/uninitialized data instead of thread 1's actual work output. Memory fences (internally handled by locking primitives and std::atomic) make sure that this kind of reordering won't occur (both at compile time and at execution time within the CPU).
6. ## Do you need a degree on top of good experience?

I went out of games into corporate stuff for a bit, and when I moved back into games, even though I aced their tests and interviewed well, they would only start me on a junior salary/position at first. After my first performance review I renegotiated, but still, I had to jump through that hoop because I was coming from a "not games" job

8. ## OOP is dead, long live OOP

Thanks. Fixed
9. ## OOP is dead, long live OOP

The first 4 are tools. The next 5 are architectural advice on use of the tools.
10. ## Do you need a degree on top of good experience?

If you ever plan on emigrating, a degree may make the process easier (automatic proof of being "skilled" to governments). Actually being able to do the job the most important thing though.
11. ## Ideal rendering engine?

D3D v Vulkan -- for D3D v GL, I'd go with D3D without hesitation, but D12/VK are pretty much the same as each other. D12 is a bit easier IMHO. RTX is just NVidia's marketing buzzword for "supports RTRT APIs" Metalness + color VS diffuse color + specular color / roughness VS glossiness isn't much of a muchness. They're two ways of encoding the exact same information. You can easily support both (which could be useful if you're sourcing artwork from different places). Cavity maps are an additional feature that work with both encodings in the same way. Super-sampling is just rendering at a higher resolution than the screen. e.g. Draw to a 4k texture and then resize it to 1080p for display on a 1080p screen. Dynamic resolution is the same thing but you pick a different intermediate/working resolution each frame, based on your framerate. Often it's used to under-sample (render at a lower rest than the screen). If money and time aren't an issue, implement them both and see which one performs better on your specific game scenes. I've been working on an indie game in a custom engine mostly-full-time for years, so kind of doing this. Before that, I was working professionally as a graphics programmer on a game engine team, so knew what I wanted -- first and foremost, my new renderer had to be easy for a graphics programmer to work with, easy to experiment with new features, easy to change. No two games that I've worked on have ever used the same renderer, so I knew that switching out algorithms easily had to be easily supported in my ideal renderer. Our game started off as traditional deferred + traditional forward (able to switch between them at runtime), then tiled deferred + tiled forward (able to switch between them at runtime), then clustered forward (only). Other features like shadows (many techniques) , SSAO, reflection probes, SSR, motion blur, planar mirrors / portals, etc, occasionally need to be added or experimented with... So there needs to be enough flexibility to slot these (or techniques that haven't yet been invented) into the pipeline. One of my inspirations for this was Horde3D's data driven rendering pipelines, where you told the engine how to render a scene with an XML file! I managed to convert Horde3D from traditional deferred to Inferred Rendering in a weekend by only writing a little bit of XML and GLSL. That impressed me a lot as a graphics programmer (it was so much nicer than the 'professional' engine I was using at work at the time...) This concept has largely caught on and is commonly referred to now as a "frame graph". Each step of an algorithm/technique is represented as a single input->process->output node, and then a data/configuration/script file uses those nodes to build a graph of instructions on how the frame will be drawn. This makes it very easy to modify the frame rendering algorithms over time my experiment with new features, but, it also allows the engine to perform lots of optimisation when it comes to D3D12 resource transition barriers / VK render passes, render target memory allocation and aliasing, and async compute as well!
12. ## Is there a way to dynamically include source code in C like in PHP?

#include does exactly that - copies the source code out of the requested file and pastes it at that location.
13. ## OOP is dead, long live OOP

I'm getting my indie game ready to exhibit at PAX at the end of October, so any free would-be-blog-writing-time is probably going to get eaten up by shader-code-polishing instead until then
14. ## Nested components within ECS? Good idea?

Please note that ECS is not a solution for inheritance hierarchies -- it's two steps removed from that. I know every single article on ECS starts off by showing some game code that's bad because it has too much inheritance and then "solves" that problem by switching to ECS... But... OOP has a rule that you should favor composition over inheritance. If code is based around lots and lots of inheritance, it's probably very incorrect according to OO theory! The immediate solution to that particular problem is to stop and actually learn how to use OOP properly, so that you can use composition instead of inheritance. Realizing that composition is the answer to your immediate issues, but then leaping to build an entire bloated framework to support a very limited form of composition when it's already a 1st class language feature, is a bit of an overreaction, to say the least. Those kinds of ECS articles are the equivalent of a TV commercial showing a bunch of slow-mo black and white videos of people trying to drill screws into wood using a hammer and getting frustrated, and then colorful videos of people using an electric screwdriver to quickly get the screws in. The electric screwdrivers that they're selling aren't necessarily bad... but the hammer isn't bad either. They just decided to show it being used incorrectly. If you go and throw out all your hammers after seeing that commercial for an electric screwdriver, that's throwing the baby out with the bathwater...
15. ## Int vs. Float Graphics Programming

GPUs traditionally couldn't do integer math at all - only floating-point and some fixed-function fixed-point HW! It's only recently that GPUs have become competent at integer math. In some situations, fixed point math on 32bit integers can be more precise that 32bit float math, so some engine actually do use 4x4 transformation matrices of integers instead of floats... But this is definitely a "weird" out of the box approach and not something that's normal.