bgfx/tools/texturev/common.sh
elvencache 96611dd944 Add HDR backbuffer support to texturev for viewing HDR textures
Texturev already supports exposure/stops as a way to view details in HDR textures. But results still clip to 1.0 due to 8 bits per channel back buffer. So not viable to view in native HDR.

Add UI menu to select scRGB (f16 HDR for windows) and HDR10 (pq/st2084 and rec2020 color primaries) and add shader code to properly display image. The intent is for SDR range content to look identical across all three modes. With additional details available in HDR modes when viewed on HDR monitor.

Running into trouble compiling fs_texture_array at the moment. So skipping the changes required in that shader.

*sdf.bin.h files changed because of changes in common.sh. Could roll the hdr code into a separate hdr.sh which would leave them be if that would be better?
2018-12-29 23:10:28 -08:00

132 lines
2.8 KiB
Bash

/*
* Copyright 2011-2018 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include <bgfx_shader.sh>
uniform vec4 u_params0;
#define u_textureLod u_params0.x
#define u_textureLayer u_params0.y
#define u_inLinear u_params0.z
#define u_ev u_params0.w
uniform vec4 u_params1;
#define u_outputFormat u_params1.x
#define u_sdrWhiteNits u_params1.y
vec3 toLinear(vec3 _rgb)
{
return pow(abs(_rgb), vec3_splat(2.2) );
}
vec3 toGamma(vec3 _rgb)
{
return pow(abs(_rgb), vec3_splat(1.0/2.2) );
}
vec3 applyExposure(vec3 _rgb)
{
vec3 rgb = mix(toLinear(_rgb.xyz), _rgb.xyz, u_inLinear);
return (rgb * pow(2.0, u_ev) );
}
vec4 toEv(vec4 _color)
{
return vec4(toGamma(applyExposure(_color.xyz) ), _color.w);
}
float toSrgbGamma(float _val)
{
if (_val <= 0.0031308)
{
return 12.92 * _val;
}
else
{
return 1.055 * pow(_val, (1.0/2.4) ) - 0.055;
}
}
vec3 toSrgbGamma(vec3 _rgb)
{
_rgb.x = toSrgbGamma(_rgb.x);
_rgb.y = toSrgbGamma(_rgb.y);
_rgb.z = toSrgbGamma(_rgb.z);
return _rgb;
}
vec3 toXyzFromSrgb(vec3 _rgb)
{
mat3 toXYZ = mat3(
0.4125564, 0.3575761, 0.1804375,
0.2126729, 0.7151522, 0.0721750,
0.0193339, 0.1191920, 0.9503041
);
return mul(toXYZ, _rgb);
}
vec3 toRec2020FromXyz(vec3 _xyz)
{
mat3 toRec2020 = mat3(
1.7166512, -0.3556708, -0.2533663,
-0.6666844, 1.6164812, 0.0157685,
0.0176399, -0.0427706, 0.9421031
);
return mul(toRec2020, _xyz);
}
vec3 toPqOetf(vec3 _color)
{
// reference PQ OETF will yield reference OOTF when
// displayed on a reference monitor employing EOTF
float m1 = 0.1593017578125;
float m2 = 78.84375;
float c1 = 0.8359375;
float c2 = 18.8515625;
float c3 = 18.6875;
vec3 Ym1 = pow(_color.xyz * (1.0/10000.0), vec3_splat(m1) );
_color = pow((c1 + c2*Ym1) / (vec3_splat(1.0) + c3*Ym1), vec3_splat(m2) );
return _color;
}
vec4 toOutput(vec4 _color, float _outputFormat, float _sdrWhiteNits)
{
// assumed that _color is linear with sRGB/rec709 primaries
// and 1.0 is SDR white point
vec3 outColor = vec3_splat(0.0);
if (_outputFormat < 0.5)
{
// output == 0 -> sRGB/rec709, apply gamma
// values over 1.0 will saturate
outColor = toSrgbGamma(saturate(_color.xyz));
}
else if (_outputFormat < 1.5)
{
// output == 1 -> scRGB, remains linear.
// values over 1.0 will appear as HDR
outColor = _color.xyz;
}
else if (_outputFormat < 2.5)
{
// output == 2 -> PQ
// change primaries from sRGB/rec709 to rec2020
vec3 _xyz = toXyzFromSrgb(_color.xyz);
outColor = toRec2020FromXyz(_xyz);
// if 1.0 is SDR white, should map to 80 nits
// but that could lead to dim results as SDR
// monitors tend to be brighter than standard
outColor = toPqOetf(outColor * _sdrWhiteNits);
}
return vec4(outColor, _color.w);
}