summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/tools/texturev/common.sh
blob: 7f91a6efdceb5f9ce07ce574b527707bda7d85cb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright 2011-2022 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
 */

#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);
}