2
* Copyright 2011, Blender Foundation.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
/// This file contains all opencl kernels for node-operation implementations
26
const sampler_t SAMPLER_NEAREST = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;
27
const sampler_t SAMPLER_NEAREST_CLAMP = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;
29
__constant const int2 zero = {0,0};
31
// KERNEL --- BOKEH BLUR ---
32
__kernel void bokehBlurKernel(__read_only image2d_t boundingBox, __read_only image2d_t inputImage,
33
__read_only image2d_t bokehImage, __write_only image2d_t output,
34
int2 offsetInput, int2 offsetOutput, int radius, int step, int2 dimension, int2 offset)
36
int2 coords = {get_global_id(0), get_global_id(1)};
38
float tempBoundingBox;
39
float4 color = {0.0f,0.0f,0.0f,0.0f};
40
float4 multiplyer = {0.0f,0.0f,0.0f,0.0f};
42
const float radius2 = radius*2.0f;
43
const int2 realCoordinate = coords + offsetOutput;
45
tempBoundingBox = read_imagef(boundingBox, SAMPLER_NEAREST, coords).s0;
47
if (tempBoundingBox > 0.0f && radius > 0 ) {
48
const int2 bokehImageDim = get_image_dim(bokehImage);
49
const int2 bokehImageCenter = bokehImageDim/2;
50
const int2 minXY = max(realCoordinate - radius, zero);
51
const int2 maxXY = min(realCoordinate + radius, dimension);
57
for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny += step, inputXy.y += step) {
58
uv.y = ((realCoordinate.y-ny)/radius2)*bokehImageDim.y+bokehImageCenter.y;
60
for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx += step, inputXy.x += step) {
61
uv.x = ((realCoordinate.x-nx)/radius2)*bokehImageDim.x+bokehImageCenter.x;
62
bokeh = read_imagef(bokehImage, SAMPLER_NEAREST, uv);
63
color += bokeh * read_imagef(inputImage, SAMPLER_NEAREST, inputXy);
71
int2 imageCoordinates = realCoordinate - offsetInput;
72
color = read_imagef(inputImage, SAMPLER_NEAREST, imageCoordinates);
75
write_imagef(output, coords, color);
78
//KERNEL --- DEFOCUS /VARIABLESIZEBOKEHBLUR ---
79
__kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2d_t bokehImage,
80
__read_only image2d_t inputSize,
81
__write_only image2d_t output, int2 offsetInput, int2 offsetOutput,
82
int step, int maxBlurScalar, float threshold, float scalar, int2 dimension, int2 offset)
84
float4 color = {1.0f, 0.0f, 0.0f, 1.0f};
85
int2 coords = {get_global_id(0), get_global_id(1)};
87
const int2 realCoordinate = coords + offsetOutput;
93
float4 multiplier_accum = {1.0f, 1.0f, 1.0f, 1.0f};
96
int minx = max(realCoordinate.s0 - maxBlurScalar, 0);
97
int miny = max(realCoordinate.s1 - maxBlurScalar, 0);
98
int maxx = min(realCoordinate.s0 + maxBlurScalar, dimension.s0);
99
int maxy = min(realCoordinate.s1 + maxBlurScalar, dimension.s1);
102
int2 inputCoordinate = realCoordinate - offsetInput;
103
float size_center = read_imagef(inputSize, SAMPLER_NEAREST, inputCoordinate).s0 * scalar;
104
color_accum = read_imagef(inputImage, SAMPLER_NEAREST, inputCoordinate);
105
readColor = color_accum;
107
if (size_center > threshold) {
108
for (int ny = miny; ny < maxy; ny += step) {
109
inputCoordinate.s1 = ny - offsetInput.s1;
110
float dy = ny - realCoordinate.s1;
111
for (int nx = minx; nx < maxx; nx += step) {
112
float dx = nx - realCoordinate.s0;
113
if (dx != 0 || dy != 0) {
114
inputCoordinate.s0 = nx - offsetInput.s0;
115
size = read_imagef(inputSize, SAMPLER_NEAREST, inputCoordinate).s0 * scalar;
116
if (size > threshold) {
117
if (size >= fabs(dx) && size >= fabs(dy)) {
118
float2 uv = {256.0f + dx * 255.0f / size,
119
256.0f + dy * 255.0f / size};
120
bokeh = read_imagef(bokehImage, SAMPLER_NEAREST, uv);
121
tempColor = read_imagef(inputImage, SAMPLER_NEAREST, inputCoordinate);
122
color_accum += bokeh * tempColor;
123
multiplier_accum += bokeh;
131
color = color_accum * (1.0f / multiplier_accum);
133
/* blend in out values over the threshold, otherwise we get sharp, ugly transitions */
134
if ((size_center > threshold) &&
135
(size_center < threshold * 2.0f))
137
/* factor from 0-1 */
138
float fac = (size_center - threshold) / threshold;
139
color = (readColor * (1.0f - fac)) + (color * fac);
142
write_imagef(output, coords, color);
147
// KERNEL --- DILATE ---
148
__kernel void dilateKernel(__read_only image2d_t inputImage, __write_only image2d_t output,
149
int2 offsetInput, int2 offsetOutput, int scope, int distanceSquared, int2 dimension,
152
int2 coords = {get_global_id(0), get_global_id(1)};
154
const int2 realCoordinate = coords + offsetOutput;
156
const int2 minXY = max(realCoordinate - scope, zero);
157
const int2 maxXY = min(realCoordinate + scope, dimension);
163
for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny ++, inputXy.y++) {
164
const float deltaY = (realCoordinate.y - ny);
165
for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx ++, inputXy.x++) {
166
const float deltaX = (realCoordinate.x - nx);
167
const float measuredDistance = deltaX * deltaX + deltaY * deltaY;
168
if (measuredDistance <= distanceSquared) {
169
value = max(value, read_imagef(inputImage, SAMPLER_NEAREST, inputXy).s0);
174
float4 color = {value,0.0f,0.0f,0.0f};
175
write_imagef(output, coords, color);
178
// KERNEL --- DILATE ---
179
__kernel void erodeKernel(__read_only image2d_t inputImage, __write_only image2d_t output,
180
int2 offsetInput, int2 offsetOutput, int scope, int distanceSquared, int2 dimension,
183
int2 coords = {get_global_id(0), get_global_id(1)};
185
const int2 realCoordinate = coords + offsetOutput;
187
const int2 minXY = max(realCoordinate - scope, zero);
188
const int2 maxXY = min(realCoordinate + scope, dimension);
194
for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny ++, inputXy.y++) {
195
for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx ++, inputXy.x++) {
196
const float deltaX = (realCoordinate.x - nx);
197
const float deltaY = (realCoordinate.y - ny);
198
const float measuredDistance = deltaX * deltaX+deltaY * deltaY;
199
if (measuredDistance <= distanceSquared) {
200
value = min(value, read_imagef(inputImage, SAMPLER_NEAREST, inputXy).s0);
205
float4 color = {value,0.0f,0.0f,0.0f};
206
write_imagef(output, coords, color);
209
// KERNEL --- DIRECTIONAL BLUR ---
210
__kernel void directionalBlurKernel(__read_only image2d_t inputImage, __write_only image2d_t output,
211
int2 offsetOutput, int iterations, float scale, float rotation, float2 translate,
212
float2 center, int2 offset)
214
int2 coords = {get_global_id(0), get_global_id(1)};
216
const int2 realCoordinate = coords + offsetOutput;
219
float2 ltxy = translate;
221
float lrot = rotation;
223
col = read_imagef(inputImage, SAMPLER_NEAREST, realCoordinate);
226
for (int i = 0; i < iterations; ++i) {
227
const float cs = cos(lrot), ss = sin(lrot);
228
const float isc = 1.0f / (1.0f + lsc);
230
const float v = isc * (realCoordinate.s1 - center.s1) + ltxy.s1;
231
const float u = isc * (realCoordinate.s0 - center.s0) + ltxy.s0;
233
cs * u + ss * v + center.s0,
234
cs * v - ss * u + center.s1
237
col += read_imagef(inputImage, SAMPLER_NEAREST_CLAMP, uv);
239
/* double transformations */
245
col *= (1.0f/(iterations+1));
247
write_imagef(output, coords, col);