Revision ed841982
Added by Leszek Koltunski almost 8 years ago
src/main/java/org/distorted/library/EffectQueuePostprocess.java | ||
---|---|---|
43 | 43 |
|
44 | 44 |
class EffectQueuePostprocess extends EffectQueue |
45 | 45 |
{ |
46 |
private static final float GAUSSIAN[] = // G(0.00), G(0.03), G(0.06), ..., G(3.00), 0 |
|
47 |
{ // where G(x)= (1/(sqrt(2*PI))) * e^(-(x^2)/2). The last 0 terminates. |
|
48 |
0.398948f, 0.398769f, 0.398231f, 0.397336f, 0.396086f, 0.394485f, 0.392537f, 0.390247f, 0.387622f, 0.384668f, |
|
49 |
0.381393f, 0.377806f, 0.373916f, 0.369733f, 0.365268f, 0.360532f, 0.355538f, 0.350297f, 0.344823f, 0.339129f, |
|
50 |
0.333229f, 0.327138f, 0.320868f, 0.314436f, 0.307856f, 0.301142f, 0.294309f, 0.287373f, 0.280348f, 0.273248f, |
|
51 |
0.266089f, 0.258884f, 0.251648f, 0.244394f, 0.237135f, 0.229886f, 0.222657f, 0.215461f, 0.208311f, 0.201217f, |
|
52 |
0.194189f, 0.187238f, 0.180374f, 0.173605f, 0.166940f, 0.160386f, 0.153951f, 0.147641f, 0.141462f, 0.135420f, |
|
53 |
0.129520f, 0.123765f, 0.118159f, 0.112706f, 0.107408f, 0.102266f, 0.097284f, 0.092461f, 0.087797f, 0.083294f, |
|
54 |
0.078951f, 0.074767f, 0.070741f, 0.066872f, 0.063158f, 0.059596f, 0.056184f, 0.052920f, 0.049801f, 0.046823f, |
|
55 |
0.043984f, 0.041280f, 0.038707f, 0.036262f, 0.033941f, 0.031740f, 0.029655f, 0.027682f, 0.025817f, 0.024056f, |
|
56 |
0.022395f, 0.020830f, 0.019357f, 0.017971f, 0.016670f, 0.015450f, 0.014305f, 0.013234f, 0.012232f, 0.011295f, |
|
57 |
0.010421f, 0.009606f, 0.008847f, 0.008140f, 0.007483f, 0.006873f, 0.006307f, 0.005782f, 0.005296f, 0.004847f, |
|
58 |
0.004432f, 0.000000f |
|
59 |
}; |
|
60 |
private static final int NUM_GAUSSIAN = GAUSSIAN.length-2; |
|
61 |
|
|
62 |
private static final int MAX_BLUR = 50; |
|
63 |
|
|
64 | 46 |
private static final int POS_DATA_SIZE= 2; // Post Program: size of the position data in elements |
65 | 47 |
private static final int TEX_DATA_SIZE= 2; // Post Program: size of the texture coordinate data in elements. |
66 | 48 |
|
... | ... | |
92 | 74 |
private static float[] mTmpMatrix = new float[16]; |
93 | 75 |
|
94 | 76 |
// BLUR effect |
77 |
private static final float GAUSSIAN[] = // G(0.00), G(0.03), G(0.06), ..., G(3.00), 0 |
|
78 |
{ // where G(x)= (1/(sqrt(2*PI))) * e^(-(x^2)/2). The last 0 terminates. |
|
79 |
0.398948f, 0.398769f, 0.398231f, 0.397336f, 0.396086f, 0.394485f, 0.392537f, 0.390247f, 0.387622f, 0.384668f, |
|
80 |
0.381393f, 0.377806f, 0.373916f, 0.369733f, 0.365268f, 0.360532f, 0.355538f, 0.350297f, 0.344823f, 0.339129f, |
|
81 |
0.333229f, 0.327138f, 0.320868f, 0.314436f, 0.307856f, 0.301142f, 0.294309f, 0.287373f, 0.280348f, 0.273248f, |
|
82 |
0.266089f, 0.258884f, 0.251648f, 0.244394f, 0.237135f, 0.229886f, 0.222657f, 0.215461f, 0.208311f, 0.201217f, |
|
83 |
0.194189f, 0.187238f, 0.180374f, 0.173605f, 0.166940f, 0.160386f, 0.153951f, 0.147641f, 0.141462f, 0.135420f, |
|
84 |
0.129520f, 0.123765f, 0.118159f, 0.112706f, 0.107408f, 0.102266f, 0.097284f, 0.092461f, 0.087797f, 0.083294f, |
|
85 |
0.078951f, 0.074767f, 0.070741f, 0.066872f, 0.063158f, 0.059596f, 0.056184f, 0.052920f, 0.049801f, 0.046823f, |
|
86 |
0.043984f, 0.041280f, 0.038707f, 0.036262f, 0.033941f, 0.031740f, 0.029655f, 0.027682f, 0.025817f, 0.024056f, |
|
87 |
0.022395f, 0.020830f, 0.019357f, 0.017971f, 0.016670f, 0.015450f, 0.014305f, 0.013234f, 0.012232f, 0.011295f, |
|
88 |
0.010421f, 0.009606f, 0.008847f, 0.008140f, 0.007483f, 0.006873f, 0.006307f, 0.005782f, 0.005296f, 0.004847f, |
|
89 |
0.004432f, 0.000000f |
|
90 |
}; |
|
91 |
private static final int NUM_GAUSSIAN = GAUSSIAN.length-2; |
|
92 |
|
|
93 |
// Support blurs consisting of the present pixel and up to MAX_BLUR pixels in each direction |
|
94 |
private static final int MAX_BLUR = 50; |
|
95 |
|
|
96 |
// The (linearly-sampled) Gaussian Blur kernels are of the size k0=1, k1=2, k2=2, k3=3, k4=3, k5=4, k6=4,... |
|
97 |
// i.e. k(i)=floor((i+3)/2). (the 'i' in k(i) means 'blur taking into account the present pixel and 'i' pixels |
|
98 |
// in all 4 directions) |
|
99 |
// We need room for MAX_BLUR of them, and sum(i=0...N, floor((i+3)/2)) = N + floor(N*N/4) |
|
100 |
private static float[] weightsCache = new float[MAX_BLUR + MAX_BLUR*MAX_BLUR/4]; |
|
101 |
private static float[] offsetsCache = new float[MAX_BLUR + MAX_BLUR*MAX_BLUR/4]; |
|
102 |
|
|
95 | 103 |
private static DistortedProgram mBlurProgram; |
96 | 104 |
private static int mRadiusH,mOffsetsH,mWeightsH,mObjDH,mMVPMatrixH; |
97 |
private float[] mWeights = new float[MAX_BLUR]; |
|
98 |
private float[] mOffsets = new float[MAX_BLUR]; |
|
105 |
private static float[] mWeights = new float[MAX_BLUR];
|
|
106 |
private static float[] mOffsets = new float[MAX_BLUR];
|
|
99 | 107 |
// another effect .... |
100 | 108 |
|
101 | 109 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
171 | 179 |
|
172 | 180 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
173 | 181 |
|
174 |
private int computeGaussianKernel(int radius)
|
|
182 |
private void computeGaussianKernel(int radius)
|
|
175 | 183 |
{ |
176 |
if( radius>=MAX_BLUR ) radius = MAX_BLUR-1;
|
|
184 |
int offset = radius + radius*radius/4;
|
|
177 | 185 |
|
178 |
float P = (float)NUM_GAUSSIAN / (radius>3 ? radius:3); |
|
179 |
float x = 0.0f; |
|
180 |
mWeights[0] = GAUSSIAN[0]; |
|
181 |
mOffsets[0] = 0.0f; |
|
182 |
float sum = GAUSSIAN[0]; |
|
183 |
int j; |
|
184 |
float z; |
|
185 |
|
|
186 |
for(int i=1; i<=radius; i++) |
|
186 |
if( weightsCache[offset]==0.0f ) |
|
187 | 187 |
{ |
188 |
x += P; |
|
189 |
j = (int)x; |
|
190 |
z = x-j; |
|
188 |
float z, x= 0.0f, P= (float)NUM_GAUSSIAN / (radius>3 ? radius:3); |
|
189 |
mWeights[0] = GAUSSIAN[0]; |
|
190 |
float sum = GAUSSIAN[0]; |
|
191 |
int j; |
|
191 | 192 |
|
192 |
mWeights[i] = (1-z)*GAUSSIAN[j] + z*GAUSSIAN[j+1]; |
|
193 |
sum += 2*mWeights[i]; |
|
194 |
} |
|
193 |
for(int i=1; i<=radius; i++) |
|
194 |
{ |
|
195 |
x += P; |
|
196 |
j = (int)x; |
|
197 |
z = x-j; |
|
195 | 198 |
|
196 |
for(int i=0; i<=radius; i++) |
|
197 |
{ |
|
198 |
mWeights[i] /= sum; |
|
199 |
} |
|
199 |
mWeights[i] = (1-z)*GAUSSIAN[j] + z*GAUSSIAN[j+1]; |
|
200 |
sum += 2*mWeights[i]; |
|
201 |
} |
|
200 | 202 |
|
201 |
// squash the weights and offsets for linear sampling |
|
202 |
int numloops = radius/2; |
|
203 |
for(int i=0; i<=radius; i++) mWeights[i] /= sum; |
|
203 | 204 |
|
204 |
for(int i=0; i<numloops; i++) |
|
205 |
{ |
|
206 |
mOffsets[i+1] = mWeights[2*i+1]*(2*i+1) + mWeights[2*i+2]*(2*i+2); |
|
207 |
mWeights[i+1] = mWeights[2*i+1] + mWeights[2*i+2]; |
|
208 |
mOffsets[i+1] /= mWeights[i+1]; |
|
209 |
} |
|
205 |
// squash the weights and offsets for linear sampling |
|
206 |
int numloops = radius/2; |
|
210 | 207 |
|
211 |
if( radius%2 == 1 ) |
|
212 |
{ |
|
213 |
int index = radius/2 +1; |
|
214 |
mOffsets[index]=mOffsets[radius]; |
|
215 |
mWeights[index]=mWeights[radius]; |
|
216 |
radius = numloops+1; |
|
217 |
} |
|
218 |
else |
|
219 |
{ |
|
220 |
radius = numloops; |
|
221 |
} |
|
208 |
weightsCache[offset] = mWeights[0]; |
|
209 |
offsetsCache[offset] = 0.0f; |
|
210 |
|
|
211 |
for(int i=0; i<numloops; i++) |
|
212 |
{ |
|
213 |
offsetsCache[offset+i+1] = mWeights[2*i+1]*(2*i+1) + mWeights[2*i+2]*(2*i+2); |
|
214 |
weightsCache[offset+i+1] = mWeights[2*i+1] + mWeights[2*i+2]; |
|
215 |
offsetsCache[offset+i+1]/= weightsCache[offset+i+1]; |
|
216 |
} |
|
217 |
|
|
218 |
if( radius%2 == 1 ) |
|
219 |
{ |
|
220 |
int index = offset + radius/2 +1; |
|
221 |
offsetsCache[index]=mOffsets[radius]; |
|
222 |
weightsCache[index]=mWeights[radius]; |
|
223 |
} |
|
222 | 224 |
|
223 |
return radius; |
|
225 |
|
|
226 |
android.util.Log.e("post", "computed kernel size "+radius+" put it into cache="+offset); |
|
227 |
} |
|
224 | 228 |
} |
225 | 229 |
|
226 | 230 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
231 | 235 |
{ |
232 | 236 |
mBlurProgram.useProgram(); |
233 | 237 |
|
234 |
int radius = computeGaussianKernel( (int)mUniforms[0] ); |
|
238 |
int radius = (int)mUniforms[0]; |
|
239 |
if( radius>=MAX_BLUR ) radius = MAX_BLUR-1; |
|
240 |
computeGaussianKernel(radius); |
|
235 | 241 |
|
236 |
float adjust = 1/h; |
|
237 |
for(int i=0; i<=radius; i++) mOffsets[i] *= adjust; |
|
242 |
int offset = radius + radius*radius/4; |
|
243 |
radius = (radius+1)/2; |
|
244 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/h; |
|
238 | 245 |
|
239 |
GLES30.glUniform1fv( mWeightsH, radius+1, mWeights,0);
|
|
246 |
GLES30.glUniform1fv( mWeightsH, radius+1, weightsCache,offset);
|
|
240 | 247 |
GLES30.glUniform1i( mRadiusH, radius); |
241 | 248 |
GLES30.glUniform2f( mObjDH , w, h ); |
242 | 249 |
|
... | ... | |
259 | 266 |
df.setAsOutput(); |
260 | 267 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight); |
261 | 268 |
|
262 |
adjust = h/w; |
|
263 |
for(int i=0; i<=radius; i++) mOffsets[i] *= adjust; |
|
269 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/w; |
|
264 | 270 |
|
265 | 271 |
// vertical blur |
266 | 272 |
GLES30.glUniform1fv( mOffsetsH ,radius+1, mOffsets,0); |
Also available in: Unified diff
BLUR: implemented caching of the BLUR kernels.