Revision ed841982
Added by Leszek Koltunski almost 9 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.