I would like to add some basic quality settings to a game we're working on:
- AA (multisampling)
- Texture filtering (trilinear, anisotropic)
- Fullscreen resolution
But I'm not sure how to do any of this, I can't seem to find a good explanation either in SDK or internet,
so I was wondering if anyone could help?
For Texture filtering, I was thinking I could make different SamplerStates within HLSL, make multiple techniques which use different SamplerStates, and then pick one technique at runtime. But I'm not sure if this is so performance-friendly?
For AA/Multisampling I thought of changing these 2 params in DXGI_SWAP_CHAIN_DESC, only the swapchain would be created before the user sets these settings (he would choose that in some kind of a menu), so it would have to be recreated with a different setting at runtime, and I don't know how to do that?
For fullscreen resolution, do I draw all data to a backbuffer/DSbuffer that has the size of the chosen resolution, and then scale it across the screen?
Having multiple techniques and picking different ones at runtime is actually fine, but in fact there's a simpler way, which is just to modify the SamplerState from the application side. You can use ID3DX11EffectSamplerVariable to to retrieve the built-in sampler state, then create a modified sampler state with just the filtering/aniso settings changed, and replace the one in the effect with yours. You can have a list of the names of sampler variables that should be affected, or just iterate over effect variables to find all the samplers.
When changing resolution or multisampling settings it's very common for the game to require you to restart for the changes to be applied. The settings are in a config file somewhere and when you start up it reads the desired ones from the file. Alternatively, you can architect your application so that the renderer is a separate component that can be shut down and restarted independent of the application.
For fullscreen resolution, yes, that's probably a reasonable way to do it. Stretching the image to desktop resolution at the end won't cost very much performance, and it avoids having to actually change the user's video mode (although you can do that if you want with the ChangeDisplaySettings Windows API). IMO, the most important thing to remember is to make the rendering aspect ratio match the monitor's aspect ratio so you don't end up with your image being stretched or squished, even if e.g. you use a 4:3 resolution on a 16:9 screen or something like that. Unfortunately, dealing with monitors, resolutions, and aspect ratios is all kinds of annoying, especially if you consider users who have multi-monitor systems. See here if you want to jump down the rabbit hole.
Question though, you say I should respect the aspect ratio of the screen, however I'm some kind of a balance freak when designing games xD
So, I wouldn't want one player to be able to see more than the other just because he's got a different backbuffer resolution/aspect ratio.
For single player games this isn't really a problem, but it is for multiplayer games.
Do you have any ideas how to handle this?
EDIT: also, I have some trouble with the multisampling settings. Some formats allow up to sampleCount 4, but only 0 quality, in which case I see no difference at all. What would be a good format to use for this?
Letterboxing is one way to handle the multiple-screen-sizes issue without actually widening the FOV.
As for the multisampling stuff, what format are you trying to use? Are you saying CheckMultisampleQualityLevels is giving you a 0 output? That means that combination of format and sample count isn't supported, but a smaller sample count or a different format might be.
CheckMultisampleQualityLevels Is always giving me either 1 or 0, no matter what sampleCount
http://en.wikipedia.org/wiki/File:Image\_cropping\_235x1.jpg \\^Lettterboxing would be something like this? Is there no other way?
No other way I can think of. I mean, if you want to display the same sized image for all players, but on different-sized monitors, how else are you going to do it? You have to either scale the image or leave some of the monitor unused for some players. (Of course, you could relax the requirement that all players see the same size of image.)
As for the multisampling, a quality level of 1 doesn't mean the quality will be bad, it just means the hardware only supports a single quality setting, so pick any sample count that gives you a quality level > 0 and you should see the multisampling in effect.
For aspect ratio, I thought that maybe I can adjust the FOV of the projection matrix for different AR, although I'm not sure how this will turn out (probably won't work out but never hurts to try, right? ). I'll have to see that later on.
CheckMultisampleQualityLevels returns 1, which means that the maximum quality level allowed is 0 (1 less than the returned value)
I have tried with multiple formats (with sampleCount 1), it always returns either 1, or 0, or some really high value(300000+) which doesn't work at all when I try it.
Even with 4x sampleCount (and quality level 0), I see no difference at all. Do I have to adjust something in the shader maybe?
Well, sure, of course you can adjust the FOV. If you're not letterboxing, the horizontal and vertical FOVs should have the same aspect ratio as the screen. But then, e.g. a 16:9 monitor might have a wider FOV than a 4:3 monitor, which you said you wanted to avoid.
I'm not sure why you're not seeing the multisampling, but you might try looking in the DirectX SDK example demos; I'm sure there's a multisampling one in there.
oh cool thx. I forgot about those
I think that fixed diagonal FOV is the best approach in dealing with different aspect ratio. This way in widescreen you can see more at left & right but less at up & down.
@}:+()___ (Smile) How would I set that up? Is that not what happens by default though? When you respect the AR of the screen
Also, I went through the DirectX tutorials but the AA code sample is for D3D9 which has a whole different approach... sigh
I mean, choosing projection matrix so view angle of screen diagonal is constant independent of screen AR. Something like
float W = 1 / sqrt(cx * cx + cy * cy);
D3DXMatrixPerspectiveLH(&mat, near * W * cx, near * W * cy, near, far);