Page 1 of 1

Can Y axis dependant gamma be a solution for TN gamma shift?

Posted: 16 Aug 2017, 12:14
by masterotaku
I've been playing Trails of Cold Steel lately (great game, by the way), and I have been developing its 3D Vision fix. You know, modifying vertex and pixel shaders (there's a WIP version in the Geforce forums, without the following option that I'm going to explain). By coincidence I found a pixel shader that controls gamma for the entire image and made a general hotkey with a multiplier. But then I thought: what if I make gamma depend on the Y axis of the screen to compensate for TN gamma shift? Here's the HLSL code:

Code: Select all

//Gamma.
// ---- Created with 3Dmigoto v1.2.63 on Sun Aug 06 15:47:29 2017

cbuffer _Globals : register(b0)
{
  float3 scene_EyePosition : packoffset(c0);
  float4x4 scene_View : packoffset(c1);
  float4x4 scene_ViewProjection : packoffset(c5);
  float4 scene_cameraNearFarParameters : packoffset(c9);
  float4 scene_viewportSizeParameters : packoffset(c10);
  float3 scene_FakeRimLightDir : packoffset(c11);
  float3 scene_GlobalAmbientColor : packoffset(c12);
  float3 scene_FogColor : packoffset(c13);
  float4 scene_FogRangeParameters : packoffset(c14);
  float3 scene_MiscParameters1 : packoffset(c15);
  float4 scene_MiscParameters2 : packoffset(c16);
  float AdditionalShadowOffset : packoffset(c17);
  float4 FilterColor : packoffset(c18) = {1,1,1,1};
  float4 FadingColor : packoffset(c19) = {1,1,1,1};
  float4 MonotoneMul : packoffset(c20) = {1,1,1,1};
  float4 MonotoneAdd : packoffset(c21) = {0,0,0,0};
  float4 GlowIntensity : packoffset(c22) = {1,1,1,1};
  float4 ToneFactor : packoffset(c23) = {1,1,1,1};
  float4 UvScaleBias : packoffset(c24) = {1,1,0,0};
  float4 GaussianBlurParams : packoffset(c25) = {0,0,0,0};
  float4 DofParams : packoffset(c26) = {0,0,0,0};
  float4 GammaParameters : packoffset(c27) = {1,1,1,0};
  float4 WhirlPinchParams : packoffset(c28) = {0,0,0,0};
}

SamplerState LinearClampSampler_s : register(s0);
Texture2D<float4> ColorBuffer : register(t0);


// 3Dmigoto declarations
#define cmp -
Texture1D<float4> IniParams : register(t120);
Texture2D<float4> StereoParams : register(t125);


void main( 
  float4 v0 : SV_Position0,
  float2 v1 : TEXCOORD0,
  out float4 o0 : SV_TARGET0)
{
  float4 r0,r1;
  uint4 bitmask, uiDest;
  float4 fDest;

  float4 iniparams = IniParams.Load(int2(1,0));
  
  r0.x = 1.10000002 * GammaParameters.x * iniparams.y + 0.5*(v1.y-0.5)*iniparams.w;
  r1.xyzw = ColorBuffer.SampleLevel(LinearClampSampler_s, v1.xy, 0).xyzw;
  r1.xyz = saturate(r1.xyz);
  o0.w = r1.w;
  r0.yzw = log2(r1.xyz);
  r0.xyz = r0.xxx * r0.yzw;
  o0.xyz = exp2(r0.xyz);
  return;
}
That "iniparams.y" is my custom multiplier, and the "+ 0.5*(v1.y-0.5)*iniparams.w" is a custom curve I made, which I can enable with a hotkey. The top of the monitor gets brighter, and the bottom gets darker. The center remains the same, obviously (if my formula is OK).

Here's a screenshot comparison: http://screenshotcomparison.com/comparison/114864

It most probably needs to be more fine tuned to be perfect, but you get the idea. I may find shaders like these for other games.

Opinions?

Re: Can Y axis dependant gamma be a solution for TN gamma sh

Posted: 16 Aug 2017, 12:51
by RealNC
Interesting idea. This would depend on the monitor (I have a monitor that has its panel installed upside-down). And it would need to be highly configurable to accommodate different viewing positions. In most cases, the effect should apply to the lower-left and lower-right corner of the screen. (Or to the upper-left and upper-right corners on upside-down panels.)

Re: Can Y axis dependant gamma be a solution for TN gamma sh

Posted: 16 Aug 2017, 13:03
by masterotaku
RealNC wrote:I have a monitor that has its panel installed upside-down.
Wow. That sounds counterintuitive. Was it a manufacturing mistake?
RealNC wrote:And it would need to be highly configurable to accommodate different viewing positions. In most cases, the effect should apply to the lower-left and lower-right corner of the screen. (Or to the upper-left and upper-right corners on upside-down panels.)
Do you mean apart from the Y axis modification I made? I know horizontal angles aren't perfect in TN either, but I though that "in general", the problem were the vertical angles.

And yes, this can be highly configurable. I can modify the starting neutral position, multiplier (it could also be a square root, power or whatever), etc. It's all in that line with the iniparams. I was asking in case there was a general math to the gamma shift, at least from a specific viewing distance. I'll be testing it more with my monitor.

Re: Can Y axis dependant gamma be a solution for TN gamma sh

Posted: 16 Aug 2017, 13:26
by RealNC
masterotaku wrote:
RealNC wrote:I have a monitor that has its panel installed upside-down.
Wow. That sounds counterintuitive. Was it a manufacturing mistake?
I don't think so. Normally on a TN, you get the severe color shift when you look at the monitor from below. Which is the best setup since that's a difficult thing to do (unless you use portrait mode). On this monitor, however, this happens when you look at the monitor from above. Which means it happens every time you stand up.

It's an AOC, btw :mrgreen:
RealNC wrote:And it would need to be highly configurable to accommodate different viewing positions. In most cases, the effect should apply to the lower-left and lower-right corner of the screen. (Or to the upper-left and upper-right corners on upside-down panels.)
Do you mean apart from the Y axis modification I made? I know horizontal angles aren't perfect in TN either, but I though that "in general", the problem were the vertical angles.
Probably a combination of both. The most extreme shift happens in the corners of the monitor, which are both the highest/lowest X and Y values.

Re: Can Y axis dependant gamma be a solution for TN gamma sh

Posted: 16 Aug 2017, 13:40
by masterotaku
RealNC wrote: Probably a combination of both. The most extreme shift happens in the corners of the monitor, which are both the highest/lowest X and Y values.
OK, thanks for the information. It will complicate my math, but it's worth a try. All of this reminds me of the HUD curvature mod I made and included in the 3D Vision fix of Skyrim Special Edition (not useful for non 3D users).

Re: Can Y axis dependant gamma be a solution for TN gamma sh

Posted: 16 Aug 2017, 13:49
by open
this is really cool and would be nice for me because of how close I sit to my monitor

Re: Can Y axis dependant gamma be a solution for TN gamma sh

Posted: 16 Aug 2017, 14:52
by Chief Blur Buster
Yes.

It could sorta work; with two big caveats:
-- Slightly reduced contrast (dynamic range headroom needed)
-- Potentially make the picture worse at other viewing angles, in exchange for making picture better at a specific angle.

Y axis dependant gamma would only help a specific head position and viewing distance.

Multiple presets can help. There'd need to be adjustments for (1) Vertical gamma intensity and (2) Vertical gamma centre shift. These two adjustments probably could be a catchall. If a third picture adjustment setting is needed, I'd recommend (3) Vertical gamma curve shaping .... a slider between a 'V curve' and a 'U curve', basically a peaking intensity adjustment. Profiles to memorize these adjustments to presets, to accomodate different head positions. You might come up with reasonable catchalls for maybe 3 average common viewing positions (top edge, centre, bottom edge), small variations from these will probably look better-than-default within a few inches of movement -- before it begins to look worse-than-default.

Also, you'd need to somewhat reduce dynamic range (e.g. 1000:1 contrast -> 800:1 contrast) to give headroom needed (Below black, and above white) to even-out gamma nonuniformities at both top and bottom end. And ideally you'll want at least a 10-bit or 12-bit panel, since gamma adjustments can amplify 6-bit + FRC(8-bit) artifacts. Potential catch-22 for TN, as they don't tend to be that many bits, but 8-bit TN might be good enough with some good 10-bit FRC and the adustments doing the gamma gradient at 10-bit.
Prerequisites: High bits (10-bit) to avoid banding in gamma gradients.

Also, even better is doing both X and Y axises, so you'd have a circle graident or even an oval gradient (gamma angles are different for horizontal than for vertical) -- there are brightness/contrast/gamma shifts in both directions. Curve shaping could get complex here, though!

Worth a try for monitor engineers, though!!