• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef API_RENDER_SHADERS_COMMON_CORE_COLOR_CONVERSION_COMMON_H
17 #define API_RENDER_SHADERS_COMMON_CORE_COLOR_CONVERSION_COMMON_H
18 
19 #ifndef VULKAN
20 #error "This is inteded to be included in shaders. Not fully ported to C/C++."
21 #endif
22 
23 #include "render_compatibility_common.h"
24 
25 // match with core/base color conversions
26 
27 // No conversion and should be used as default
28 #define CORE_COLOR_CONVERSION_TYPE_NONE 0
29 // sRGB to linear conversion
30 #define CORE_COLOR_CONVERSION_TYPE_SRGB_TO_LINEAR 1
31 // Linear to sRGB conversion
32 #define CORE_COLOR_CONVERSION_TYPE_LINEAR_TO_SRGB 2
33 
34 /**
35  * Calculate luma.
36  */
CalcLuma(const vec3 color)37 float CalcLuma(const vec3 color)
38 {
39     // Rec. 601 luma
40     return 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
41 }
42 
43 /**
44  * Calculate simplified luma.
45  */
CalcLumaFxaa(const vec3 color)46 float CalcLumaFxaa(const vec3 color)
47 {
48     // Rec. 601 luma based approximation
49     return color.g * (0.587 / 0.299) + color.r;
50 }
51 
52 /**
53  * Luma weight.
54  */
LumaWeight(const float luma)55 float LumaWeight(const float luma)
56 {
57     return (1.0 / (1.0 + luma));
58 }
59 
60 /**
61  * Tonemap based on luma.
62  */
TonemapLuma(const vec3 color,const float luma,const float range)63 vec3 TonemapLuma(const vec3 color, const float luma, const float range)
64 {
65     return color / (1.0 + luma / range);
66 }
67 
68 /**
69  * Inverse tonemap based on luma.
70  */
TonemapLumaInv(const vec3 color,const float luma,const float range)71 vec3 TonemapLumaInv(const vec3 color, const float luma, const float range)
72 {
73     return color / (1.0 - luma / range);
74 }
75 
76 /**
77  * Convert sRGB to linear RGB.
78  * https://en.wikipedia.org/wiki/SRGB
79  */
SrgbToLinear(const vec3 srgb)80 vec3 SrgbToLinear(const vec3 srgb)
81 {
82     const float mlow = 1.0f / 12.92f;
83     const float mhigh = 1.0f / 1.055f;
84 
85     const vec3 high = pow((srgb + 0.055f) * mhigh, vec3(2.4f));
86     const vec3 low = srgb * mlow;
87     const bvec3 cutoff = lessThan(srgb, vec3(0.04045f));
88     return mix(high, low, cutoff);
89 }
90 
91 /**
92  * Convert linear RGB to sRGB.
93  * https://en.wikipedia.org/wiki/SRGB
94  */
LinearToSrgb(const vec3 linear)95 vec3 LinearToSrgb(const vec3 linear)
96 {
97     const float mlow = 12.92f;
98     const float mhigh = 1.055f;
99 
100     const vec3 high = pow(linear, vec3(0.416f)) * mhigh - 0.055f;
101     const vec3 low = linear * mlow;
102     const bvec3 cutoff = lessThan(linear, vec3(0.0031308f));
103     return mix(high, low, cutoff);
104 }
105 
106 /**
107  * Convert RGB to YCoCg.
108  * https://en.wikipedia.org/wiki/YCoCg
109  */
rgbToYCoCg(const vec3 rgb)110 vec3 rgbToYCoCg(const vec3 rgb)
111 {
112     const float y = dot(rgb, vec3(0.25, 0.5, 0.25));
113     const float co = dot(rgb, vec3(0.5, 0.0, -0.5));
114     const float cg = dot(rgb, vec3(-0.25, 0.5, -0.25));
115     return vec3(y, co, cg);
116 }
117 
118 /**
119  * Convert YCoCg to RGB
120  * https://en.wikipedia.org/wiki/YCoCg
121  */
yCoCgToRgb(const vec3 ycocg)122 vec3 yCoCgToRgb(const vec3 ycocg)
123 {
124     const float y = ycocg.r;
125     const float co = ycocg.g;
126     const float cg = ycocg.b;
127     return vec3(y + co - cg, y + cg, y - co - cg);
128 }
129 
130 /**
131  * Brightness matrix
132  * https://docs.rainmeter.net/tips/colormatrix-guide/
133  */
BrightnessMatrix(float brightness)134 mat4 BrightnessMatrix(float brightness)
135 {
136     mat4 matrix = mat4(1.0);
137     matrix[3].xyz = vec3(brightness);
138     return matrix;
139 }
140 
141 /**
142  * Contrast matrix
143  * https://docs.rainmeter.net/tips/colormatrix-guide/
144  */
ContrastMatrix(float contrast)145 mat4 ContrastMatrix(float contrast)
146 {
147     const float t = (1.0 - contrast) / 2.0;
148 
149     mat4 matrix = mat4(1.0);
150     matrix[0].x = contrast;
151     matrix[1].y = contrast;
152     matrix[2].z = contrast;
153 
154     matrix[3].xyz = vec3(t);
155 
156     return matrix;
157 }
158 
159 /**
160  * Saturation matrix
161  * https://docs.rainmeter.net/tips/colormatrix-guide/
162  */
SaturationMatrix(float saturation)163 mat4 SaturationMatrix(float saturation)
164 {
165     const vec3 luminance = vec3(0.3086, 0.6094, 0.0820);
166 
167     const float t = (1 - saturation);
168     const float sr = t * luminance.r;
169     const float sg = t * luminance.g;
170     const float sb = t * luminance.b;
171 
172     vec3 red = vec3(sr + saturation, sr, sr);
173     vec3 green = vec3(sg, sg + saturation, sg);
174     vec3 blue = vec3(sb, sb, sb + saturation);
175 
176     mat4 matrix = mat4(1.0);
177 
178     matrix[0].xyz = red;
179     matrix[1].xyz = green;
180     matrix[2].xyz = blue;
181 
182     return matrix;
183 }
184 
185 /**
186  * Hue shift color
187  * https://gist.github.com/mairod/a75e7b44f68110e1576d77419d608786?permalink_comment_id=3195243#gistcomment-3195243
188  */
HueShift(vec3 color,float hueShift)189 vec3 HueShift(vec3 color, float hueShift)
190 {
191     float hueRadians = radians(hueShift);
192     const vec3 k = vec3(0.57735, 0.57735, 0.57735);
193     float cosAngle = cos(hueRadians);
194     return vec3(color * cosAngle + cross(k, color) * sin(hueRadians) + k * dot(k, color) * (1.0 - cosAngle));
195 }
196 
197 /**
198  * Kelvin to Rgb approximation for range between 1000K and 40000K
199  * https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
200  */
KelvinToRgb(float kelvin)201 vec3 KelvinToRgb(float kelvin)
202 {
203     float temp = kelvin / 100.0;
204     float r, g, b;
205 
206     if (temp <= 66.0) {
207         r = 1.0;
208         g = clamp(0.39008157876901960784 * log(temp) - 0.63184144378862745098, 0.0, 1.0);
209         b = temp <= 19.0 ? 0.0 : clamp(0.54320678911019607843 * log(temp - 10.0) - 1.19625408914, 0.0, 1.0);
210     } else {
211         r = clamp(1.29293618606274509804 * pow(temp - 60.0, -0.1332047592), 0.0, 1.0);
212         g = clamp(1.12989086089529411765 * pow(temp - 60.0, -0.0755148492), 0.0, 1.0);
213         b = 1.0;
214     }
215 
216     return vec3(r, g, b);
217 }
218 
219 /**
220  * Color grading for srgb color
221  * https://www.shadertoy.com/view/lsdXRn
222  */
ColorGrading(vec3 color,float colorTemperature,vec3 colorTemperatureStrength,float colorTemperatureBrightnessNormalization,vec3 presaturation,vec3 gain,vec3 lift,vec3 gamma)223 vec3 ColorGrading(vec3 color, float colorTemperature, vec3 colorTemperatureStrength,
224     float colorTemperatureBrightnessNormalization, vec3 presaturation, vec3 gain, vec3 lift, vec3 gamma)
225 {
226     // Calculate original brightness using luminance coefficients
227     float originalBrightness = dot(color, vec3(0.2126, 0.7152, 0.0722)); // For srgb colors
228     // Adjust color based on color temperature and strength
229     color = mix(color, color * KelvinToRgb(colorTemperature), colorTemperatureStrength);
230     // Calculate new brightness after temperature adjustment
231     float newBrightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
232     // Normalize brightness to maintain consistency
233     color *= mix(1.0, (newBrightness > 1e-6) ? (originalBrightness / newBrightness) : 1.0,
234         colorTemperatureBrightnessNormalization);
235     // Adjust saturation by mixing with grayscale value
236     color = mix(vec3(dot(color, vec3(0.2126, 0.7152, 0.0722))), color, presaturation);
237     // Apply lift, gain and gamma adjustments
238     return pow((gain * 2.0) * (color + (((lift * 2.0) - vec3(1.0)) * (vec3(1.0) - color))), vec3(0.5) / gamma);
239 }
240 
241 #endif // API_RENDER_SHADERS_COMMON_CORE_COLOR_CONVERSION_COMMON_H
242