Project

General

Profile

« Previous | Next » 

Revision ed841982

Added by Leszek Koltunski almost 8 years ago

BLUR: implemented caching of the BLUR kernels.

View differences:

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