Re: Architecting and programming a graphics engine in C++ & OpenGL
"Nathan Martz" <[email protected]> Sat, 19 Mar 2011 12:16:31 -0700
| Newsgroups | gmane.games.devel.sweng |
|---|---|
| Message-ID | <[email protected]> |
So much good advice on this thread. I'm loathe to add to it, but I want to highlight a "big picture" trend that might help give you context and inform how you proceed, especially if you decide to focus on rendering architecture and write your own from the ground up. Here it is... Over time rendering will be less and less about the care and feeding of GPUs and more about (embarrassingly) parallel computation. For the last decade and change, the dominant model in graphics has been "CPU makes a big list of requests, GPU turns them into pixels." That's still sort of true, but becoming less so every day. As CPUs gain cores and as GPUs become increasingly programmable and CPU like, rendering is becoming all about deciding how you divide up work across a series of (usually heterogeneous) processors. At the start of this console generation, people started spinning the renderer off onto a separate thread from the main game. A few years later, console and PC engines started to use multiple threads just for rendering (usually some sort of parallel command buffer generation). In the past few years (earlier on the PS3), people started adopting hybrid CPU/GPU techniques, moving "GPU work" like post-processing, skinning, anti-aliasing, lighting, occlusion, etc. off the GPU and onto the CPU (especially SPUs). When you look at the really cutting edge stuff, especially in the world of DX10/11, you see even more of complex CPU/GPU integration. Over time, GPUs and CPUs will be even harder to tell apart and provide more and more options for how do divide the work between them. It's an awesome, but also scarily complex and open ended future. The one thing I can say with confidence is that to be competitive, future renderers will need to do the majority of their computation in parallel across multiple processors. And that's where the really important, but also really not easy problems are. As we all know, parallel programming is really tricky, doubly so if you are starting with a big renderer that was never designed with it in mind. Fortunately, there's tons of great literature on the topic (much of which like Data Oriented Design and Mike Acton's publications have already been mentioned). It's definitely something you should be thinking and reading about if you want to try your hand at writing your own renderer. Of course, there's a universe of places to start and things to explore, but if your goal is to land a job at a high end game dev studio, there are, for my money, few more impressive things you could demonstrate than a renderer that is thoughtfully and productively parallel. Good luck with whatever you decide to do! -Nathan From: [email protected] [mailto:[email protected]] On Behalf Of Tommy Brett Sent: Friday, March 18, 2011 11:26 AM To: [email protected] Subject: Re: [Sweng-Gamedev] Architecting and programming a graphics engine in C++ & OpenGL On Fri, Mar 18, 2011 at 1:30 PM, Massimo Del Zotto <[email protected]> wrote: 2011/3/18 Tommy Brett <[email protected]> ... pursue my original intended career as a games programmer, ... it will render planets with atmosphere and real time shadows, or die trying, and in any case will serve as my main portfolio piece when I eventually start applying for positions. Hello Tommy, I also started working on my engine for this same reason ("as portfolio"). I don't know how other people are set but I suppose you will do more or less what I've been doing up to now so I hope you will find my advices useful. What are the best practices for building a graphics engine in C++? Exactly how OOP should I go? A stupid answer would be "as far as you need but no more". When I started working on my system I tried to make pretty much of everything OOP. I eventually figured out that OOP is not always the best tool for the job. Some systems are natively data-oriented and some will inevitably need reinterpret_cast (oh, the horror). You will have to get your hands dirty. In some cases, having less abstraction can be helpful. In general, my design rarely relies on objects but is really based on "subsystems" which (as an implementative detail) emerge from aggregating objects. Rather than objects, I really think in terms of "protocols" (quite similar to "network protocols"). You might say this is exactly what objects are made for. Yes but the whole point is: don't be afraid of steering away from OOP every once in a while. The more you go "high level" the more OOP will result useful but at low level, bad surprises might await you and the systems have to be coupled somehow anyway. This is why I mentioned 'how much is too much', because from my own experimentation and from reading previous gamedev mailing list discussions, OOP is clearly not always the best method for graphics engines. As for how to write good C++ engines I'd suggest to remember that while C++ has no explicit "interface" classes, they are indeed there and they will help you a lot (the compiler also seems to like them pretty much IMHO). Many people seem to forget this so just in case... Interfaces are definitely something I've gotten comfortable with using in my AS3 programming, it's a neat alternative to deriving from a base class. How should I handle the use of multiple shaders on chunks of geometry? You're not going to solve this right now. Use iterative design. You really have no choice, this would cause you to meltdown your head. I don't quite figure out what you mean by "multiple shaders on chunks of geometry". Are you referring to multiple materials? Are you referring to multipass techniques? Your first step is surely to figure out what you mean by "shader" because when you have an engine, "shaders" as most APIs provide will probably lack something here or there. For example my "engine shaders" provide special binding points to link engine logic. Say you want to make everything fade to black progressively as player's health drops to 0. They also include additional information which are not part of the "API shader" such as blend mode to use (this is similar to DirectX "effects") and other additional stuff. Now, those requirements weren't introduced in a day but evolved out of the needs. This is why some people advises to "write games not engines"... you really need to understand what you need for real before you can hope to understand a way to solve the problem in a reusable, "engine" way. Both materials and multi pass rendering techniques. I suppose it's a broad question and I think you're right with the 'just code it' approach. What I meant was, given a collection of meshes, each with their own textures and effects, what would be the best way to organize those chunks of geometry data, how would I manage engine state from chunk to chunk? E.g. switching shaders, would switching shaders mid render even be viable? Currently my idea for a graphics engine involves something like an engine class that takes render packets of data, has some sort of ability to sort them into an order that best facilitates speedy rendering, and changes its state depending on the information in the packets. This makes me think about http://realtimecollisiondetection.net/blog/?p=86 but you probably don't mean this kind of low-level sort... or do you? According to what you write next, it seems you're thinking at a much higher level which apparently seems to be scenegraph's responsability. I don't know. As a final note here, the link I provided is effective but until you don't finalize the systems involved it creates a strong dependancy which will slow you down (where in the hierarchy should I put this batch?). Start easy first! Leave the order emerge from your design first. Benchmark. Refine. Repeat. Be aware of premature optimization. When in doubt write easy to understand code, the bugs will generally emerge some time later, often because of change in requirements, and you want the code to NOT bite you. You probably have plenty of perf anyway and your first objective is get the work done. So I suppose what I'm looking for are book suggestions, or perhaps open-sourced graphics engines that I could look at and learn from ... the trouble is there aren't any such positions available where I live, and relocation would be difficult to justify based upon the possibly low salary expectations of a junior position It is always a good idea to consider already available engines. You really have to look around you (at least your state as very minimum) and figure out what to do as there's a serious social aspect to consider here. From the few demos I've given out I can say that presenting something which is 100% yours is fairly impressive, especially for small realities, it seems that the idea of having somebody which can work out problems top-to-bottom is very appreciated. Problem is that it takes a lot - a lot - of effort to get to the first demo. It still takes a lot to go to the second as you will keep working on it which in fact will result in less demos (or reuse of the very same one). Second problem is, as other people have said, turning a pre-made engine into something yours is indeed valuable skill as well, which is likely much more important if you're going to apply in consolidated companies. Not my case here... :-( Pre-made engines give you a great kickstart (it's awesome for morale)! On the cons, I have to admit some projects I've looked at seemed to be halting after a while. Let's not hide the fact: once you choose an engine you choose a line of thinking and this implies you will think your design in a certain way. Which is easier. The day you get a problem which is not directly solvable by the engine, you start having issues. I say this because a friend of mine had exactly this problem. Its initial enthusiasm of having "parallax mapping and shadows everywhere" quickly faded when he figured out the hard truth: the engine prevented him from understanding the problems involved. Of course, if you take your time to make sure you know what you're doing, this should not be a problem and you'll get best of both worlds. I just wanted to drop this warning. Your reply and other people's has given me a perspective that I didn't consider before - taking someone elses engine and modifying it to suit my own needs would certainly be an exemplary show of skill, especially for studios that use 3rd party tools themselves Experimenting a bit with modding games such as Unreal or Quake is very useful IMHO. If you haven't tried making a Quake map then you should really try right now. Take a look at the formats. Do some black box analysis. Take your time... if you can afford it. Also try to figure out what assets you have access to and make sure you understand the data encoded in ("know your data"). I've scratched my head more than a year in making a shader work according to a "reference implementation" before figuring out that the "reference" asset pipeline is way smarter than I originally believed, let's say it works around data format's dumbness... Actually it's funny you mention Quake mapping, when I started fiddling with games and programming, I started with programming q-basic and making Doom maps, which eventually progressed to Quake and Half-Life (I rather enjoyed Worldcraft, even though it took forever and a day for them to release decent texture mapping tools) and ignited my desire to become a programmer (luckily I was young enough at the time that abusing goto didn't stick with me for long). It's also why I have Michael Abrash's Black Book, I'm fascinated by fps engines and how they calculate potentially visible data from a vast map. I hope this helps, Massimo Greatly so, thank you. _______________________________________________ Sweng-Gamedev mailing list [email protected] http://lists.midnightryder.com/listinfo.cgi/sweng-gamedev-midnightryder. com _______________________________________________ Sweng-Gamedev mailing list [email protected] http://lists.midnightryder.com/listinfo.cgi/sweng-gamedev-midnightryder.com