cancel
Showing results for 
Search instead for 
Did you mean: 

sRGB/gamma/color whoes, conversion from PSVR to CV1

ox
Honored Guest
Ok this may seem a bit "unusual" question but, I am working on a title currenty on work for PSVR ( PS4 ) and currently having it working as well on PC / CV1, all in house propietary engine so "all coded by hand".

Now they story goes as simply as "colours don't quite look the same", in essence what you see on CV1 ( compared to the PSVR side of things ) is quite a bit "darker" now the hues seems to be "mostly correct" but it's literally maybe a matter of brightness/gamma/dynamic (???) ..

Try as I may I cannot find any "simple way" to make things look "as similar as possible", if instead of using SRGB for textures I use a LINEAR space everything looks yes quite much brighter ( now even a bit "too much" ) but you get lot of "match banding" as well.

True I saw a certain "difference" between SDK 1.6 and the latest one SDK 1.8 that I applied yesterday but still "not that perfect".

Now the questions are

- is there any parameter(s)/something that maybe could be touch in the "compositor" to adjust something like brightness/contrast/gamma ?

- any other thing that could be done ?

I thinking "in a worst case scenario" maybe to have a "final render pass" with some shader to perform some ( nonlinear ? ) correction to adjust the stuff but I'd love to avoid it as that would mean "quite a bit of GPU time lost".

Also, little things I noted, "the black is not really black", when I look into the CV1 with a totally black screen I see a sort of "gradient" going from black to a sort of "dark reddish" from bottom to top, is that normal ?

One more thing, those "stupid rays/internal reflection" .. I guess the only thing is to avoid "high contrast scenes" because I don't think anything can be done about it ? Those are really quite annoying and it means one has to "color balance" all scenes/things one by one because otherwise you get artifacts.

Not a very good idea those Fresnel Lenses ..

Cheers.

8 REPLIES 8

ox
Honored Guest
So "OK" there is the thing, I set OVR_FORMAT_R8G8B8A8_UNORM for the ovr_CreateTextureSwapChainDX() in place of OVR_FORMAT_R8G8B8A8_UNORM_SRGB, then I added a "final shader" between my last rendering and pEyeRenderTexture[the_eye_index];

So I tried "a bit of this and that" from just trying to touch brightenss/contrast ( linear transformation ) to manually apply a simple function gamma correction ...

Nothing seems to work "good" enough, it seems as soon as you start just using a bit of "amplification" (i.e. for example result.rgb = input.rgb * contrast; you get lot of match banding in "low colours".

The thing is to me looks like sRGB should be "the correct thing to go" but it's like the CV1 has some sort of "strange range" of colours like "too dark is too dark", "too white is too white" there's really "something odd" I don't get what's going on.

It's really frustrating I have two things side by side and I cannot make the look similar, thing is I really don't know what is the nature of the problem I am seeing.

Anyone knows or want to talk about ?

Cheers.





cybereality
Grand Champion
I'll see if anyone on the team knows about this.

volgaksoy
Expert Protege
OX, I don't know how the PSVR system works, and I don't know how far off things look for you. Do you know what the gamma profile for the PSVR display is? Is it sRGB, or something else? I'm not personally asking for an answer here, but you should be aware of these things when making sure the PSVR & CV1 visuals look comparable. I can give you some insight on how things are supposed to work.

This is perhaps going to sound a bit confusing at first, but here it goes. The Oculus compositor expects all eye textures to be rendered into in linear space *from the GPU shader's point-of-view*. By that we mean that when the formats are set up correctly, even an sRGB texture is actually linear when you sample from it and write to it as a render target in your shader. FP16 formats are linear as well. Note that you actually do NOT want to use OVR_FORMAT_R8G8B8A8_UNORM because while that's a linear format, its bit are not distributed nicely enough to provide band-free rendering when it's displayed on a perceptually-linear display (e.g. sRGB or gamma 2.2).

If you have done your rendering using R8G8B8A8_UNORM, then you would want to emulate some form of gamma correction (e.g. pow(2.2)). So I would hope that the lighting math in your shader was modified to be gamma-aware. Similarly, you would make sure that the output is applying some form of gamma curve such as pow(1.0/2.2) on the output color. If that's something that you don't care about perhaps you actually have no dynamic lighting, then it might be OK.

When everything is said and done, the Oculus compositor actually applies color correction to the incoming eye textures to make sure the luminance response is along the lines of what is expected regardless of what the display panel would have done as a "dumb pass-thru" display.

ox
Honored Guest
Hi,
honestly I don't know the gamma profile of PSVR, but I THINK it SHOULD be sRGB  "everything works sRGB in the code".

Now I am not sure about another thing now then, all colours in the vertex definitions as well are also set as type DXGI_FORMAT_R8G8B8A8_UNORM, as far as I know "everything works in a linear fashion" until you get to the final render target where all is defined as sRGB.

So you say that in theory "if i put all R8G8B8A8_UNORM" and then before to pass to compositor I do a gamma of 2.2 I should theorectically see something "more similar" ? I think I tried that yesterday and was still "a bit too dark".

The strange thing is, in _UNORM "everything is too bright" ( but bit more similar to what I see on PSVR ) but in _SRGB everything is too dark.

I wonder, can make this try too, what would happen if I leave all _SRGB and I change the vertex definitions so every instance of "colour" instead of being DXGI_FORMAT_R8G8B8A8_UNORM I replace it with _SRGB too, I have not tried that yet.

From what you say "by nose" give me the feeling that "what you'd need" is maybe an R10G10B10A10_UNORM format instead ? Can it be used ?

ox
Honored Guest
Hi,
I understand "even less".

If I put all _UNORM and then I ran a final shader like this one

float4 main(MIXER_OUT ov) : S_TARGET_OUTPUT
{
    float4 color;
    float3 cc;

    color = Texture0.Sample(Samp_0, ov.TexCoord0);

    cc = color.rgb;
    cc = pow(cc, 2.2);

    return float4(cc,color.a);
}

Everything gets "with holes", it's like low colours ( blue-purpler tints) get replaced by black, an overall side by side comparision of "same stuff rendered on the two things" clearly shows again "I am too dark".

The more that gamma approaches 1, the more stuff looks "bit closer" BUT you very soon start to see LOT of match banding and everything gets the feeling of "being a bit washed out".

Let's say that "by kinda nose" ( eye ) a gamma of 1.4 gives "a much better result than 2.2" but it's still too dark, at '1' ( so no gamma corr at all ) some stuff is more similar but the match banding is tremendous.

I'll see if I'll been able to get some answers "from the other side" but I am really puzzled, it seems there's no easy simple correction thing that makes the thing match and it puzzles me, you can get "kinda similar" but not really similar and the moment you start "pumping up a bit colours" you get this terrible match banding .

Why is that "so sensitive" ?

Mah .. it's quite a mistery ..



volgaksoy
Expert Protege
You're getting banding because you're applying a gamma curve to an 8-bit value, and not undoing the curve before submitting the final color out of the shader.

I would highly recommend this article which also contains some explanation towards what the Oculus compositor does. https://gamedevdaily.io/the-srgb-learning-curve-773b7f68cf7a

ox
Honored Guest
Hi,
so .. seems I found out what I was doing wrong.

What I was doing wrong was taking some sample code ( i.e. the samples supplied ) study it a bit, think "I should got the most part", implement some stuff as it was in the example and then find out that "what was there was not exactly what you needed".

Now I forgot to say two things ,

1. that I am using MSAA
2. that there's a point where I stolen bits and pieces of the OculusTexture class from OculusRoomTiny

Now if you look at main.cpp of that, around line 55 you will see :

        ovrTextureSwapChainDesc desc = {};
        desc.Type = ovrTexture_2D;
        desc.ArraySize = 1;
        desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;

However a bit further down ..

            D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
            rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;


Second problem by trying to understand how MSAA was working/used I had a look into the OculusRoomTinyAdvanced example and I found out that the MSAA textures where declared and used like DXGI_FORMAT_R8G8B8A8_UNORM, not knowing precisely "why" I assumed "maybe for some reasons has to be like that ?".

In short .. putting both thing to DXGI_FORMAT_R8G8B8A8_UNORM_SRGB sorted all the problems out.

Now the stuff looks nearly identical in both versions.


cybereality
Grand Champion
Awesome. Thanks for following up with the solution.