6ba3fa55e8f7a8d9d5a459ca05e40c4869572682
[blender-staging.git] / intern / opencolorio / gpu_shader_display_transform.glsl
1 uniform sampler2D image_texture;
2 uniform sampler3D lut3d_texture;
3 uniform bool predivide;
4
5 #ifdef USE_CURVE_MAPPING
6 /* Curve mapping parameters
7  *
8  * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
9  * (this ones pretyt much copies stuff from C structure.)
10  */
11 uniform sampler1D curve_mapping_texture;
12 uniform int curve_mapping_lut_size;
13 uniform ivec4 use_curve_mapping_extend_extrapolate;
14 uniform vec4 curve_mapping_mintable;
15 uniform vec4 curve_mapping_range;
16 uniform vec4 curve_mapping_ext_in_x;
17 uniform vec4 curve_mapping_ext_in_y;
18 uniform vec4 curve_mapping_ext_out_x;
19 uniform vec4 curve_mapping_ext_out_y;
20 uniform vec4 curve_mapping_first_x;
21 uniform vec4 curve_mapping_first_y;
22 uniform vec4 curve_mapping_last_x;
23 uniform vec4 curve_mapping_last_y;
24 uniform vec3 curve_mapping_black;
25 uniform vec3 curve_mapping_bwmul;
26
27 float read_curve_mapping(int table, int index)
28 {
29         /* TODO(sergey): Without -1 here image is getting darken after applying unite curve.
30          *               But is it actually correct to subtract 1 here?
31          */
32         float texture_index = float(index) / float(curve_mapping_lut_size  - 1);
33         return texture1D(curve_mapping_texture, texture_index) [table];
34 }
35
36 float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
37 {
38         if (x <= first[0]) {
39                 if (use_curve_mapping_extend_extrapolate[table] == 0) {
40                         /* no extrapolate */
41                         return first[1];
42                 }
43                 else {
44                         if (curve_mapping_ext_in_x[table] == 0.0)
45                                 return first[1] + curve_mapping_ext_in_y[table] * 10000.0;
46                         else
47                                 return first[1] + curve_mapping_ext_in_y[table] * (x - first[0]) / curve_mapping_ext_in_x[table];
48                 }
49         }
50         else if (x >= last[0]) {
51                 if (use_curve_mapping_extend_extrapolate[table] == 0) {
52                         /* no extrapolate */
53                         return last[1];
54                 }
55                 else {
56                         if (curve_mapping_ext_out_x[table] == 0.0)
57                                 return last[1] - curve_mapping_ext_out_y[table] * 10000.0;
58                         else
59                                 return last[1] + curve_mapping_ext_out_y[table] * (x - last[0]) / curve_mapping_ext_out_x[table];
60                 }
61         }
62         return 0.0;
63 }
64
65 float curvemap_evaluateF(int table, float value)
66 {
67         float mintable_ = curve_mapping_mintable[table];
68         float range = curve_mapping_range[table];
69         float mintable = 0.0;
70         int CM_TABLE = curve_mapping_lut_size - 1;
71
72         float fi;
73         int i;
74
75         /* index in table */
76         fi = (value - mintable) * range;
77         i = int(fi);
78
79         /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */
80         if (fi < 0.0 || fi > float(CM_TABLE)) {
81                 return curvemap_calc_extend(table, value,
82                                             vec2(curve_mapping_first_x[table], curve_mapping_first_y[table]),
83                                             vec2(curve_mapping_last_x[table], curve_mapping_last_y[table]));
84         }
85         else {
86                 if (i < 0) return read_curve_mapping(table, 0);
87                 if (i >= CM_TABLE) return read_curve_mapping(table, CM_TABLE);
88
89                 fi = fi - float(i);
90                 return (1.0 - fi) * read_curve_mapping(table, i) + fi * read_curve_mapping(table, i + 1);
91         }
92 }
93
94 vec4 curvemapping_evaluate_premulRGBF(vec4 col)
95 {
96         vec4 result = col;
97         result[0] = curvemap_evaluateF(0, (col[0] - curve_mapping_black[0]) * curve_mapping_bwmul[0]);
98         result[1] = curvemap_evaluateF(1, (col[1] - curve_mapping_black[1]) * curve_mapping_bwmul[1]);
99         result[2] = curvemap_evaluateF(2, (col[2] - curve_mapping_black[2]) * curve_mapping_bwmul[2]);
100         result[3] = col[3];
101         return result;
102 }
103 #endif
104
105 void main()
106 {
107         vec4 col = texture2D(image_texture, gl_TexCoord[0].st);
108 #ifdef USE_CURVE_MAPPING
109         col = curvemapping_evaluate_premulRGBF(col);
110 #endif
111         if (predivide && col[3] > 0.0 && col[3] < 1.0) {
112                 float inv_alpha = 1.0 / col[3];
113                 col[0] *= inv_alpha;
114                 col[1] *= inv_alpha;
115                 col[2] *= inv_alpha;
116         }
117
118         /* NOTE: This is true we only do de-premul here and NO premul
119          *       and the reason is simple -- opengl is always configured
120          *       for straight alpha at this moment
121          */
122         gl_FragColor = OCIODisplay(col, lut3d_texture);
123 }