Project

General

Profile

« Previous | Next » 

Revision 4c1dd6e9

Added by Leszek Koltunski about 8 years ago

Beginnings of support for postprocessing Effects.

View differences:

src/main/java/org/distorted/library/Distorted.java
382 382
    return EffectQueue.getMax(EffectTypes.FRAGMENT.ordinal());
383 383
    }
384 384

  
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386
/**
387
 * Returns the maximum number of Postprocess effects.
388
 *
389
 * @return The maximum number of Postprocess effects
390
 */
391
  public static int getMaxPostprocess()
392
    {
393
    return EffectQueue.getMax(EffectTypes.POSTPROCESS.ordinal());
394
    }
395

  
385 396
///////////////////////////////////////////////////////////////////////////////////////////////////
386 397
/**
387 398
 * Sets the maximum number of Matrix effects that can be stored in a single EffectQueue at one time.
......
444 455
    {
445 456
    return EffectQueue.setMax(EffectTypes.FRAGMENT.ordinal(),max);
446 457
    }
458

  
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
/**
461
 * Sets the maximum number of Postprocess effects that can be stored in a single EffectQueue at one time.
462
 * This can fail if:
463
 * <ul>
464
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
465
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
466
 *     before the Fragment Shader gets compiled, i.e. before the call to {@link #onSurfaceCreated}. After this
467
 *     time only decreasing the value of 'max' is permitted.
468
 * <li>Furthermore, this needs to be called before any instances of the DistortedEffects class get created.
469
 * </ul>
470
 *
471
 * @param max new maximum number of simultaneous Postprocess Effects. Has to be a non-negative number not greater
472
 *            than Byte.MAX_VALUE
473
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
474
 */
475
  public static boolean setMaxPostprocess(int max)
476
    {
477
    return EffectQueue.setMax(EffectTypes.POSTPROCESS.ordinal(),max);
478
    }
447 479
  }
src/main/java/org/distorted/library/EffectNames.java
236 236
   * <p>
237 237
   * Unity: contrastLevel = 1
238 238
   */
239
  SMOOTH_CONTRAST  ( EffectTypes.FRAGMENT,   new float[] {1.0f}           , 1, true, false );
239
  SMOOTH_CONTRAST  ( EffectTypes.FRAGMENT,   new float[] {1.0f}           , 1, true, false ),
240 240
  // add new Fragment effects here...
241 241

  
242
  /////////////////////////////////////////////////////////////////////////////////
243
  // POSTPROCESSING EFFECTS.
244
  // Always 3 Uniforms: 1 per-effect interpolated value + 2 dimensional center.
245
 /**
246
   * Blur the area around the center.
247
   * <p>
248
   * Uniforms: (radius,centerX,centerY)
249
   * <p>
250
   * Unity: radius==0
251
   */
252
  BLUR             ( EffectTypes.POSTPROCESS,new float[] {0.0f}          , 1, false, true );
253

  
242 254
///////////////////////////////////////////////////////////////////////////////////////////////////
243 255
  
244 256
  private static final int MAXDIM = 4;  // maximum supported dimension of an effect  
src/main/java/org/distorted/library/EffectQueue.java
62 62
    mMaxIndex     = index;
63 63
    mObjectID     = id;
64 64

  
65
    if( mMax[mMaxIndex]>0 )
65
    int max = mMax[mMaxIndex];
66

  
67
    if( max>0 )
66 68
      {
67
      mName            = new int[mMax[mMaxIndex]];
68
      mUniforms        = new float[numUniforms*mMax[mMaxIndex]];
69
      mInter           = new Dynamic[3][mMax[mMaxIndex]];
70
      mCurrentDuration = new long[mMax[mMaxIndex]];
71
      mID              = new long[mMax[mMaxIndex]];
72
      mIDIndex         = new byte[mMax[mMaxIndex]];
73
      mFreeIndexes     = new byte[mMax[mMaxIndex]];
69
      mName            = new int[max];
70
      mUniforms        = new float[numUniforms*max];
71
      mInter           = new Dynamic[3][max];
72
      mCurrentDuration = new long[max];
73
      mID              = new long[max];
74
      mIDIndex         = new byte[max];
75
      mFreeIndexes     = new byte[max];
74 76
     
75
      for(byte i=0; i<mMax[mMaxIndex]; i++) mFreeIndexes[i] = i;
77
      for(byte i=0; i<max; i++) mFreeIndexes[i] = i;
76 78

  
77 79
      if( numCache>0 )
78 80
        {
79
        mCache = new float[numCache*mMax[mMaxIndex]];
81
        mCache = new float[numCache*max];
80 82
        }
81 83
      }
82 84
   
src/main/java/org/distorted/library/EffectQueuePostprocess.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.library;
21

  
22
import android.opengl.GLES20;
23

  
24
import org.distorted.library.message.EffectMessage;
25
import org.distorted.library.type.Data1D;
26
import org.distorted.library.type.Data2D;
27
import org.distorted.library.type.Dynamic1D;
28
import org.distorted.library.type.Dynamic2D;
29
import org.distorted.library.type.Static1D;
30
import org.distorted.library.type.Static2D;
31

  
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33

  
34
class EffectQueuePostprocess extends EffectQueue
35
  {
36
  private static final int NUM_UNIFORMS = 3;
37
  private static final int NUM_CACHE    = 0;
38
  private static final int INDEX = EffectTypes.POSTPROCESS.ordinal();
39

  
40
  private static int mNumEffectsH;
41
  private static int mTypeH;
42
  private static int mUniformsH;
43
  private static int mObjDH;
44

  
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46

  
47
  EffectQueuePostprocess(long id)
48
    { 
49
    super(id,NUM_UNIFORMS,NUM_CACHE,INDEX );
50
    }
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

  
54
  static void getUniforms(int mProgramH)
55
    {
56
    mNumEffectsH= GLES20.glGetUniformLocation( mProgramH, "pNumEffects");
57
    mTypeH      = GLES20.glGetUniformLocation( mProgramH, "pType");
58
    mUniformsH  = GLES20.glGetUniformLocation( mProgramH, "pUniforms");
59
    mObjDH      = GLES20.glGetUniformLocation( mProgramH, "u_objD");
60
    }
61

  
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63
  
64
  synchronized void compute(long currTime) 
65
    {
66
    if( currTime==mTime ) return;
67
    if( mTime==0 ) mTime = currTime;
68
    long step = (currTime-mTime);
69
   
70
    for(int i=0; i<mNumEffects; i++)
71
      {
72
      if( mInter[0][i]!=null && mInter[0][i].interpolateMain(mUniforms ,NUM_UNIFORMS*i, mCurrentDuration[i], step) )
73
        {
74
        for(int j=0; j<mNumListeners; j++)
75
          EffectMessageSender.newMessage( mListeners.elementAt(j),
76
                                          EffectMessage.EFFECT_FINISHED,
77
                                         (mID[i]<<EffectTypes.LENGTH)+EffectTypes.POSTPROCESS.type,
78
                                          mName[i],
79
                                          mObjectID);
80

  
81
        if( EffectNames.isUnity(mName[i], mUniforms, NUM_UNIFORMS*i) )
82
          {
83
          remove(i);
84
          i--;
85
          continue;
86
          }
87
        else mInter[0][i] = null;
88
        }
89

  
90
      if( mInter[1][i]!=null )
91
        {
92
        mInter[1][i].interpolateMain(mUniforms, NUM_UNIFORMS*i+1, mCurrentDuration[i], step);
93
        }
94

  
95
      mCurrentDuration[i] += step;
96
      }
97
     
98
    mTime = currTime;  
99
    }  
100

  
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

  
103
  protected void moveEffect(int index)
104
    {
105
    mUniforms[NUM_UNIFORMS*index  ] = mUniforms[NUM_UNIFORMS*(index+1)  ];
106
    mUniforms[NUM_UNIFORMS*index+1] = mUniforms[NUM_UNIFORMS*(index+1)+1];
107
    mUniforms[NUM_UNIFORMS*index+2] = mUniforms[NUM_UNIFORMS*(index+1)+2];
108
    }
109

  
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

  
112
  synchronized void send(float objX, float objY)
113
    {
114
    GLES20.glUniform1i( mNumEffectsH, mNumEffects);
115
    GLES20.glUniform2f( mObjDH , objX, objY);
116

  
117
    if( mNumEffects>0 )
118
      {
119
      GLES20.glUniform1iv( mTypeH    ,  mNumEffects, mName    ,0);
120
      GLES20.glUniform4fv( mUniformsH,2*mNumEffects, mUniforms,0);
121
      }
122
    }
123

  
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
// blur
126

  
127
  synchronized long add(EffectNames eln, Data1D degree, Data2D center)
128
    {
129
    if( mMax[INDEX]>mNumEffects )
130
      {
131
      if( degree instanceof Dynamic1D)
132
        {
133
        mInter[0][mNumEffects] = (Dynamic1D)degree;
134
        }
135
      else if( degree instanceof Static1D)
136
        {
137
        mInter[0][mNumEffects] = null;
138
        mUniforms[NUM_UNIFORMS*mNumEffects] = ((Static1D)degree).getX();
139
        }
140
      else return -1;
141

  
142
      if( center instanceof Dynamic2D)
143
        {
144
        mInter[1][mNumEffects] = (Dynamic2D)center;
145
        }
146
      else if( center instanceof Static2D)
147
        {
148
        mInter[1][mNumEffects] = null;
149
        mUniforms[NUM_UNIFORMS*mNumEffects+1] = ((Static2D)center).getX();
150
        mUniforms[NUM_UNIFORMS*mNumEffects+2] = ((Static2D)center).getY();
151
        }
152
      else return -1;
153

  
154
      return addBase(eln);
155
      }
156
      
157
    return -1;
158
    }
159
  }
src/main/java/org/distorted/library/EffectTypes.java
31 31
  /**
32 32
   * Effects that change the ModelView matrix: Rotations, Moves, Shears, Scales.
33 33
   */
34
  MATRIX   ( 0x1 ),   // we will need to perform bitwise operations on those - so keep the values 1,2,4,8...
34
  MATRIX      ( 0x1 ),  // we will need to perform bitwise operations on those - so keep the values 1,2,4,8...
35 35
  /**
36 36
   * Effects that get executed in the Vertex shader: various distortions of the vertices.
37 37
   */
38
  VERTEX   ( 0x2 ),
38
  VERTEX      ( 0x2 ),
39 39
  /**
40 40
   * Effects executed in the Fragment shader: changes of color, hue, transparency levels, etc.
41 41
   */
42
  FRAGMENT ( 0x4 );
42
  FRAGMENT    ( 0x4 ),
43
  /**
44
   * Postprocessing done to the texture the first stage fragment shader created (if this queue is
45
   * empty, the first stage skips this intermediate texture)
46
   */
47
  POSTPROCESS ( 0x8 );
43 48

  
44 49
///////////////////////////////////////////////////////////////////////////////////////////////////
45 50

  
......
63 68
                      // to EffectQueueMatrix.setMax(int)
64 69

  
65 70
    maxtable[1] = 5;  // Max 5 VERTEX Effects
66
    maxtable[2] = 5;  // Max 3 FRAGMENT Effects
71
    maxtable[2] = 5;  // Max 5 FRAGMENT Effects
72
    maxtable[3] = 5;  // Max 5 POSTPROCESSING Effects
67 73
    }
68 74
///////////////////////////////////////////////////////////////////////////////////////////////////
69 75
  }
src/main/res/raw/post_fragment_shader.glsl
1
//////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                          //
3
//                                                                                          //
4
// This file is part of Distorted.                                                          //
5
//                                                                                          //
6
// Distorted is free software: you can redistribute it and/or modify                        //
7
// it under the terms of the GNU General Public License as published by                     //
8
// the Free Software Foundation, either version 2 of the License, or                        //
9
// (at your option) any later version.                                                      //
10
//                                                                                          //
11
// Distorted is distributed in the hope that it will be useful,                             //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                           //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                            //
14
// GNU General Public License for more details.                                             //
15
//                                                                                          //
16
// You should have received a copy of the GNU General Public License                        //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                       //
18
//////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
varying vec2 vTexCoordinate;
21
uniform sampler2D u_Texture;
22
uniform vec2 u_objD;
23
uniform int fNumEffects;                   // total number of postprocessing effects
24

  
25
#if NUM_POSTPROCESS>0
26
uniform int pType[NUM_POSTPROCESS];        // their types.
27
uniform vec4 pUniforms[2*NUM_POSTPROCESS]; // i-th effect is 2 consecutive vec4's: [2*i], [2*i+1].
28
                                           //
29

  
30
//////////////////////////////////////////////////////////////////////////////////////////////
31
// BLUR EFFECT
32

  
33
void blur(out vec4 color)
34
  {
35
  color = vec4(0.0);
36

  
37
  float blurSizeH = 1.0 / u_objD.x;
38
  float blurSizeV = 1.0 / u_objD.y;
39

  
40
  for (int x = -4; x <= 4; x++)
41
    for (int y = -4; y <= 4; y++)
42
      color += texture( u_Texture, vec2(vTexCoord.x + x * blurSizeH, vTexCoord.y + y * blurSizeV) ) / 81.0;
43
  }
44

  
45
#endif
46

  
47
//////////////////////////////////////////////////////////////////////////////////////////////
48

  
49
void main()
50
  {
51
  vec4 pixel = texture2D(u_Texture,v_TexCoordinate);
52

  
53
#if NUM_POSTPROCESS>0
54
  for(int i=0; i<fNumEffects; i++)
55
    {
56
    if( pType[i]==BLUR ) blur(pixel);
57
    }
58
#endif
59

  
60
  gl_FragColor = pixel;
61
  }
src/main/res/raw/post_vertex_shader.glsl
1
//////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                          //
3
//                                                                                          //
4
// This file is part of Distorted.                                                          //
5
//                                                                                          //
6
// Distorted is free software: you can redistribute it and/or modify                        //
7
// it under the terms of the GNU General Public License as published by                     //
8
// the Free Software Foundation, either version 2 of the License, or                        //
9
// (at your option) any later version.                                                      //
10
//                                                                                          //
11
// Distorted is distributed in the hope that it will be useful,                             //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                           //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                            //
14
// GNU General Public License for more details.                                             //
15
//                                                                                          //
16
// You should have received a copy of the GNU General Public License                        // 
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                       //
18
//////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
attribute vec2 a_Position;       // Per-vertex position information we will pass in.
21
attribute vec2 a_TexCoordinate;  // Per-vertex texture coordinate information we will pass in.
22
varying   vec2 v_TexCoordinate;  //
23

  
24
//////////////////////////////////////////////////////////////////////////////////////////////
25
// empty 2D vertex shader for postprocessing
26

  
27
void main()
28
  {
29
  v_TexCoordinate = a_TexCoordinate;
30
  gl_Position = vec4(a_Position, 0.0, 1.0);
31
  }

Also available in: Unified diff