Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 29 Jul 2001
Offline Last Active Yesterday, 08:48 PM

#5263066 Phong versus Screen-Space Ambient Occlusion (with source code)

Posted by Promit on 21 November 2015 - 07:21 PM

We have to say it's not physically correct to multiply them because it's an ambient value but it's the common trick to multiply after the lighting.
That will result to have the ambient occlusion visible even if the zone is lighted but it's an artistic value.

Yeah but nothing about SSAO is physically correct, it's an aesthetic hack. What we want is hemispherical occlusion applied to a GI light contribution, but here in the real world...

#5263025 C++ and C#

Posted by Promit on 21 November 2015 - 02:00 PM

C++ is THE tool of professional development, for better or worse. There are many reasons for that. But in most cases - certainly as an indie developer - C# is far more productive and much easier and faster to work with. So you have to decide on your goals. If professional employment is something you're aiming at, then it may well be worth learning C++ despite the long, arduous road. That's particularly true for more specialized architectural roles (engine, graphics, physics, etc programmers). On the other hand, if you really want to focus on creating a game and having a usable product, C# is the better choice. This gets you to the point of making a polished, tested, tuned game in a finished playable state much faster and is much more useful if your focus is game design.

#5260674 Water rendering

Posted by Promit on 05 November 2015 - 05:45 PM

Most of the ocean water rendering you see today in movies or games is a derivative of the Tessendorf work, first seen in Titanic. Short version, it involves summing up various octaves of noise to come up with something that follows the same general structure of ocean waves in terms of geometry and normals. Once you've learned what this particular technique looks like, you will see it everywhere. For a more modern, game centric approach, you can look to Assassin's Creed.


As a high level overview: the first challenge is generating water that is geometrically plausible. Tessendorf covers this for deep ocean environments but isn't appropriate for shallow water or shorelines. In simple cases you can actually skip the geometric generation entirely, but you'll never get a truly convincing look without it. There's a fair bit of work on doing full blown fluid simulation models for water in more contained conditions. Most of the realtime-useful ones are based on smoothed-particle hydrodynamics (SPH). A search for "SPH water" should produce plenty of results.


Next step is the core shading work. At its heart this simply involves computing reflection and refraction components, sampling textures for both of those components, and putting it together with a BRDF specular model. The reflection and refraction components are both fundamentally functions of V and N, which means that you can get away without any geometric generation just by moving normal maps across the surface and sampling them, then blending using the fresnel term. This will fall apart at oblique viewing angles but works reasonably well at sharper viewing angles or longer viewing distances. The lighting model can be as trivial as Blinn-Phong specular with a ludicrously high specular power, but you'll see good visual benefits to using a proper physically based BRDF. C/LEAN mapping will do a lot to clean up the aliasing or roughness inconsistencies that will occur from a surface with such high frequency detail. That sparkling specular effect at the tips of the waves is the key of what makes water rendering work visually. Subsurface scattering also adds a lot of visual punch.


The last step is "embellishments". Sea foam, splashes, edge effects, etc. These do a lot to add presence and a sense of reality to the water, rather than having it simply slice through surfaces. I don't have a lot of information on this part, unfortunately. The Assassin's Creed paper does cover some of it.


While that's not comprehensive, it does provide the core elements you'll need and plenty to start on. IMO the easiest thing to do is render a gigantic flat plane, tile octaves of noise from a normal map across it, render the refraction with a clip plane and render to texture, use a stock skybox for the reflection, and get the basic fresnel blend and lighting correct. It's much easier to start doing the fancy stuff once you have that skeleton to work with.

#5260588 Quickest way to glBufferSubData

Posted by Promit on 05 November 2015 - 01:24 AM

You may want to look into whether OES_mapbufferis available on your target platforms.



From what I understand, lets say I have a buffer that can hold 1000 sprites. Then I fill this buffer with 1000 sprites. So the buffer is now full. Then I want another sprite, now this is where I orphan. I make a call out to glBufferData() using NULL as my data param. And I get a fresh block of memory
Now I can write to this block of mem and I still have all the previous data (the first 1000 sprites) sitting out on the GPU
The only caveat is that any time I orphan I have to reallocate the buffer space.  Right?

When you call it with a NULL data pointer (and the same size as before), you do not "get a fresh block of memory". It merely tells the driver that you no longer care about what was in the memory. It may be the same memory, it may be new memory, it may be a mix of things. Your sprites may or may not be preserved, depending on what the system's doing at that moment in time. All draw calls prior to that point will not be affected, but there are no promises after that. It is legal to ignore the call entirely. It's an optimization technique to try and avoid stalls when uploading data, not a rule about how things behave.


In general, one of two things will happen. Either the driver will need the contents of that buffer for a submitted draw call that has not yet been sent through the pipeline, in which case it will allocate a new block of memory. This case is going to perform slowly. Or the driver is done with the memory, and it will simply do nothing. Doing nothing is pretty fast. Long story short, doing this more than about once per frame on any given buffer is more or less equivalent to simply manually creating new buffers and tends to show poor performance. The bad news is that all of the sane mechanisms for handling buffers in OpenGL did not make it into ES 2.0 and exist only as extensions. MapBuffer is good, MapBufferRange is better. If you cannot use MapBufferRange, it's best to simply allocate lots of buffers ahead of time and avoid uploading data to them more than once per frame. 


Also consider that ES devices are typically running unified memory and that simply omitting VBOs outright and submitting draw calls from client memory may be faster than doing any of this. Maybe.


Lastly, I recommend reading this book chapter.

#5259507 How to did Spelunky not get sued

Posted by Promit on 28 October 2015 - 10:28 PM

While I'm not familiar with the specific case you're describing, I think this might be generally informative: https://en.wikipedia.org/wiki/Video_game_clone

Note in particular:

In present-day law, it is upheld that game mechanics of a video game are part of its software, and are generally ineligible for copyright.

#5259380 ETC and PVRTC dead to an unified compression ?

Posted by Promit on 28 October 2015 - 01:17 AM

I think you mean ASTC as the common format, not BC. Hopefully everyone will settle on ASTC in a few years but we're not there yet and there's a lot of legacy devices.

#5259317 Which to learn first: Wwise or FMOD?

Posted by Promit on 27 October 2015 - 03:13 PM

There's very little to "learn" with FMOD. You create a "system" object which can load sounds (either all-at-once or streamed), or play them (once or looped) which returns a channel object. Then you can change properties of the channel they're assigned to such as volume or pitch. There, now you know FMOD.

#5258554 Help with specs for laptop

Posted by Promit on 22 October 2015 - 01:00 PM

I'm going to make this really super simple: Start with the Dell Inspiron 15" 7000 series. You don't have to choose this particular machine, but it's an excellent baseline for the Skylake laptops that are now coming out in terms of both price and features. One neat touch on this particular machine is that it ships with a single 8 GB SO-DIMM and an empty slot for whenever you feel like upgrading. All of the laptops are now in the process of upgrading to Intel Skylake (aka "Intel 6th gen Core") so it's probably best to wait for that to roll out everywhere. It'll take through the end of the year for all of the manufacturers to update. The aforementioned Inspiron is out of the gate early and seems to be awesome. Might even take a look at the Amazon SSD equipped version.


Looking for something with a more robust build and premium appointments? Dell XPS 15. Smaller? Inspiron 13 or XPS 13. More gaming-oriented? Probably the Lenovo Y50, although we're still waiting on a Skylake version. Want the coolest, expensivest, fanciest thing on the block? Surface Book.

#5257165 Warning for glVertexAttribPointer

Posted by Promit on 13 October 2015 - 09:48 PM

First things first. Since you are using C++, why are you using horrible C casts? There is static_cast and reinterpret_cast. They show intent much clearer, are easier to locate when searching a document and actually avoid some of the potential pitfalls of C casts.

Then, a way to solve the warning is to use

static_cast<const char*>(0) + size
Or, if the editor decides to mangle my template again turn a null pointer into a const char* pointer and add your offset. Good old pointer arithmetic will then deal with the rest.


In this particular case, I don't see the point of making a stink about it. OpenGL's the one doing an abusive integer-pointer cast and there's no particular ambiguity about what's happening, or particular potential for unexpected behavior. So C or C++ style cast, do whatever. Hilariously enough, your idea of adding to a zero pointer? Undefined behavior. Whoops. It's just a messy thing to do in the first place.

#5256578 Do you use friend to avoid security problems ?

Posted by Promit on 10 October 2015 - 02:51 PM

I mean, as long as you're complaining about implementation in headers, you might as well also complain about templates which force implementation in headers.

"As long as we're complaining about Alzheimer's, we might as well also complain about cancer."

At this point you're not complaining about public/private/protected, you're just complaining about the header and compilation unit system which has long outgrown its usefulness and is being replaced with proper modules in a future C++ version once they nail down the spec.

Just to be clear, my claim is that private/protected semantics have no value in C++ as it exists today. Yes, the compilation model got us here. But as long as we're living with that, I simply reject any idea that these features accomplish anything but a false feel-good sense of "ah, totally encapsulated". Encapsulation in C++ requires polymorphic interfaces or pImpl, period. (Or in some cases, stripped headers, which are a messy game to play.) Once you apply these techniques, access semantics no longer have any meaning anyway.



Heck, the C# and Java code that love so much requires you to put interface and implementation in the same file. You can't even hide your code in the same way the C header/source system does. The only time you don't see the entire implementation is when you are dealing with a library and only have the compiled metadata to go against.

I've seen this complaint many times over the years - there is no file in these languages that sums up the public interface without the implementation details, unless of course you write up a polymorphic interface and implement it separately. The ability to see the public interface is instead consigned to IDE based metadata or code analysis tools. I have mixed feelings about this. But in the course of practical and professional work, the C++ version has created far more problems for me while the C# version is inconvenient at worst. Of course this leads back to the C++ compilation model, which is a disease that goes far beyond something as trivial as private/protected.


At the end of the day, I can't think of an instance across 15 years of personal and professional C++ development work where I've avoided a single bug or mistake by marking variables as private. The borderline cases are easily dealt with by naming convention. Since client code is bound by the compilation model to the total definition of the class anyway, you just don't get the expected benefits.


The primary goal of the post is to secure the end user of the API but the part about attacks was not bad.

No idea what you're talking about.

#5256574 Do you use friend to avoid security problems ?

Posted by Promit on 10 October 2015 - 02:01 PM

Private is very important in that it lets you provide a clean API to end users that allow you to modify the internals with minimal recompilation and preserve class invariants. Protected has a few useful applications (for holding an interface's destructor for example if you don't want someone destroying an object via the interface).

Except we're talking about C++, which immediately and catastrophically fucks this up by making the private internals part of the header anyway. So then we end up with tricks ranging from vanilla polymorphic interfaces to pImpl idiom variations, rendering the whole exercise pointless.

Like others have said, access semantics, like other things in the language, are there to protect the programmer from making mistakes and to help enforce good code design

And the moment you inflict friend, we're not talking about good code design anymore, we're talking about continuing hacks where the core design has already gone awry. It's worth noting that a number of modern languages get by just fine without access semantics. My argument is they may get along better without them and that the very use of access semantics represents total failure of encapsulation in C++. Why? Because even if I can't access the internal details of a class, I can see them just fine due to other encapsulation-puncturing issues in the language. That serves to bind clients to implementation details anyway, in the absence of pImpl type techniques. Lacking the relevant semantics forces you to deal with the interface/implementation divide directly. This is not the case in Java or C#, which implement sane module systems and let you alter implementations without impacting clients.


If you consider C++ private/protected semantics relevant to your code design, it's time for a redesign.

#5256483 Do you use friend to avoid security problems ?

Posted by Promit on 09 October 2015 - 11:42 PM

I honestly think private/protected are worthless features in C++. They serve some purpose in module-based languages like Java or C#, but their basic use in C++ is just not particularly compelling.

#5256258 C# Garbage Collection and performance/stalls

Posted by Promit on 08 October 2015 - 01:07 PM

The Microsoft .NET runtime offers significant control over when and how the garbage collector runs: https://msdn.microsoft.com/en-us/library/System.GC_methods(v=vs.110).aspx

#5255937 What's the best system on which to learn ASM?

Posted by Promit on 06 October 2015 - 08:35 PM

Get yourself a Raspberry Pi2B or a BeagleBone Black.  These are ARM boards -- the ARM processor is way simpler than the x86 even though they're of the same relative vintage (ARM is RISC, x86 is Swiss Army knife).  In addition to learning ASM, you can futz with blinkenlights so you can really feel close to the metal.  Learn to love the smell of rosin-core solder, it's the smell of victory.

This is the way to go. Most of the other suggestions are useless - while Z80s, 6502s, 68ks are kinda cute to play with, they have no relevance to modern development or modern processor design. x86 is extremely useful and relevant but also complicated and psychotic. MIPS was relevant once and continues to be a popular university choice, and resources are readily available. The trouble is just that very few MIPS chips are out there and what is generally lives in highly constrained embedded systems so it's just not a very real-world skill.


ARM strikes a great balance of being a nice, modern design that is highly relevant to work today, but still fairly straightforward to learn.

#5255452 The f***ing horrible nfl madden games!

Posted by Promit on 03 October 2015 - 08:50 PM

It would not be legal under any circumstances to use real teams, real players, real mascots, etc, if that's what you're asking.