1

In a Direct3D application filled with Sprite objects from D3DX, I would like to be able to globally adjust the brightness and contrast. The contrast is important, if at all possible.

I've seen this question here about OpenGL: Tweak the brightness/gamma of the whole scene in OpenGL

But that doesn't give me what I would need in a DirectX context. I know this is something I could probably do with a pixel shader, too, but that seems like shooting a fly with a bazooka and I worry about backwards compatibility with older GPUs that would have to do any shaders in software. It seems like this should be possible, I remember even much older games like the original Half Life having settings like this well before the days of shaders.

EDIT: Also, please note that this is not a fullscreen application, so this would need to be something that would just affect the one Direct3D device and that is not a global setting for the monitor overall.

Community
  • 1
  • 1
Chris McElligott Park
  • 3,057
  • 3
  • 27
  • 25
  • This will not solve your problem, but I think everyone using the word gamma in image processing context should read this: http://www.alvyray.com/Memos/9_gamma.pdf – Laserallan Aug 27 '09 at 21:16

6 Answers6

5

A lot of games do increasing brightness by, literally, applying a full screen poly over the screen with additive blending. ie

SRCBLEND = ONE
DESTBLEND = ONE

and then applying a texture with a colour of (1, 1, 1, 1) will increase the brightness(ish) of every pixel by 1.

To adjust contrast then you need to do similar but MULTIPLY by a constant factor. This will require blend settings as follows

SRCBLEND = DESTCOLOR
DESTBLEND = ZERO

This way if you blend a pixel with a value of (2, 2, 2, 2) then you will change the contrast.

Gamma is a far more complicated beast and i'm not aware of a way you can fake it like above.

Neither of these solutions is entirely accurate but they will give you a result that looks "slightly" correct. Its much more complicated doing either way properly but by using those methods you'll see effects that will look INCREDIBLY similar to various games you've played, and that's because that's EXACTLY what they are doing ;)

Goz
  • 61,365
  • 24
  • 124
  • 204
  • This sounds very promising -- I will experiment with this in the morning and see how it works in practice. Thanks! – Chris McElligott Park Aug 28 '09 at 00:23
  • Okay, actually, I already checked it out and it's perfect! Obviously it is not 100% accurate as you say, but it's older-GPU friendly, quite efficient overall, and gives a result that is plenty good enough. Thanks, once again! – Chris McElligott Park Aug 28 '09 at 00:36
2

For a game I made in XNA, I used a pixel shader. Here is the code. [disclaimer] I'm not entirely sure the logic is right and some settings can have weird effects (!) [/disclaimer]

float offsetBrightness = 0.0f;    //can be set from my C# code, [-1, 1]
float offsetContrast   = 0.0f;    //can be set from my C# code  [-1, 1]

sampler2D screen : register(s0);  //can be set from my C# code

float4 PSBrightnessContrast(float2 inCoord : TEXCOORD0) : COLOR0
{
    return (tex2D(screen, inCoord.xy) + offsetBrightness) * (1.0 + offsetContrast);
}

technique BrightnessContrast
{
    pass Pass1 { PixelShader = compile ps_2_0 PSBrightnessContrast(); }
}
Jodi
  • 900
  • 7
  • 14
  • can you explain how do you set the offsets dynamically? Or do you recompile shader code everytime after changing? – Ulterior Jan 13 '12 at 08:13
1

You didn't specify which version of DirectX you're using, so I'll assume 9. Probably the best you can do is to use the gamma-ramp functionality. Pushing the ramp up and down increases or decreases brightness. Increasing or decreasing the gradient alters contrast.

Kylotan
  • 18,290
  • 7
  • 46
  • 74
  • Only works in fullscreen, exclusive mode, unfortunately. Maybe this isn't possible for non-fullscreen applications without a pixel shader, I don't know. – Chris McElligott Park Aug 27 '09 at 19:30
  • The docs imply that it could work in windowed mode. In practice I expect it will depend on your graphics card and drivers. – Kylotan Aug 27 '09 at 21:57
  • Unfortunately not: "When setting new ramp levels, keep in mind that that the levels you set in the arrays are only used when your application is in full-screen, exclusive mode." (from the link) – Chris McElligott Park Aug 28 '09 at 12:53
  • Strange. It also says, "Because the gamma ramp is a property of the swap chain, the gamma ramp can be applied when the swap chain is windowed." I guess it means it can be applied, but it won't do anything. Which is not so useful. :) – Kylotan Aug 28 '09 at 16:20
1

Another approach is to edit all your textures. It would basically be the same approach as the gamma map, except you apply the ramp manually to the pixel data in each of your image files to generate the textures.

Kylotan
  • 18,290
  • 7
  • 46
  • 74
1

Just use a shader. Anything that doesn't at least support SM 2.0 is ancient at this point.

BigSandwich
  • 2,768
  • 2
  • 22
  • 26
0

The answers in this forum may be of help, as I have never tried this.

http://social.msdn.microsoft.com/Forums/en-US/windowsdirectshowdevelopment/thread/95df6912-1e44-471d-877f-5546be0eabf2

James Black
  • 41,583
  • 10
  • 86
  • 166