Project

General

Profile

« Previous | Next » 

Revision d6e94c84

Added by Leszek Koltunski about 7 years ago

progress with Postprocessing.

View differences:

src/main/java/org/distorted/library/Distorted.java
20 20
package org.distorted.library;
21 21

  
22 22
import android.content.Context;
23
import android.content.res.Resources;
23 24
import android.opengl.GLES20;
24 25
import org.distorted.library.program.*;
25 26

  
......
62 63
   * This way we can have two different DistortedEffects sharing the FRAGMENT queue.
63 64
   */
64 65
  public static final int CLONE_FRAGMENT= 0x8;
66
   /**
67
   * When creating an instance of a DistortedEffects from another instance, clone the PostProcess Effects.
68
   * <p>
69
   * This way we can have two different DistortedEffects sharing the POSTPROCESS queue.
70
   */
71
  public static final int CLONE_POSTPROCESS= 0x10;
65 72
  /**
66 73
   * When creating an instance of a DistortedTree from another instance, clone the children Nodes.
67 74
   * <p>
68 75
   * This is mainly useful for creating many similar sub-trees and rendering then at different places
69 76
   * on the screen with (optionally) different Effects.
70 77
   */
71
  public static final int CLONE_CHILDREN= 0x10;
78
  public static final int CLONE_CHILDREN= 0x20;
72 79

  
73 80
  static int[] mMainProgramAttributes;
81
  static int[] mPostProgramAttributes;
82

  
83
  static int mainProgramH, postProgramH;
74 84

  
75 85
///////////////////////////////////////////////////////////////////////////////////////////////////
76 86

  
......
102 112
 */
103 113
  public static void onCreate(final Context context)
104 114
  throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
105
    { 
106
    final InputStream vertexStream   = context.getResources().openRawResource(R.raw.main_vertex_shader);
107
    final InputStream fragmentStream = context.getResources().openRawResource(R.raw.main_fragment_shader);
115
    {
116
    final Resources resources = context.getResources();
108 117

  
109
    DistortedProgram mainProgram = new DistortedProgram(vertexStream,fragmentStream);
110
    int programH = mainProgram.getProgramHandle();
111
    GLES20.glUseProgram(programH);
118
    final InputStream mainVertexStream   = resources.openRawResource(R.raw.main_vertex_shader);
119
    final InputStream mainFragmentStream = resources.openRawResource(R.raw.main_fragment_shader);
120

  
121
    DistortedProgram mainProgram = new DistortedProgram(mainVertexStream,mainFragmentStream);
122
    mainProgramH = mainProgram.getProgramHandle();
123
    GLES20.glUseProgram(mainProgramH);
112 124
    mainProgram.bindAndEnableAttributes();
113 125
    mMainProgramAttributes = mainProgram.getAttributes();
114 126

  
......
119 131
    GLES20.glCullFace(GLES20.GL_BACK);
120 132
    GLES20.glFrontFace(GLES20.GL_CW);
121 133

  
122
    EffectQueueFragment.getUniforms(programH);
123
    EffectQueueVertex.getUniforms(programH);
124
    EffectQueueMatrix.getUniforms(programH);
125
    DistortedTexture.getUniforms(programH);
134
    EffectQueueFragment.getUniforms(mainProgramH);
135
    EffectQueueVertex.getUniforms(mainProgramH);
136
    EffectQueueMatrix.getUniforms(mainProgramH);
137
    DistortedTexture.getUniforms(mainProgramH);
138

  
139
    final InputStream postVertexStream   = resources.openRawResource(R.raw.post_vertex_shader);
140
    final InputStream postFragmentStream = resources.openRawResource(R.raw.post_fragment_shader);
141

  
142
    DistortedProgram postProgram = new DistortedProgram(postVertexStream,postFragmentStream);
143
    postProgramH = postProgram.getProgramHandle();
144
    GLES20.glUseProgram(postProgramH);
145
    postProgram.bindAndEnableAttributes();
146
    mPostProgramAttributes = postProgram.getAttributes();
147

  
148
    EffectQueuePostprocess.getUniforms(postProgramH);
126 149

  
127 150
    DistortedTree.reset();
128 151
    EffectMessageSender.startSending();
src/main/java/org/distorted/library/DistortedEffects.java
40 40
  private static long mNextID =0;
41 41
  private long mID;
42 42

  
43
  private EffectQueueMatrix    mM;
44
  private EffectQueueFragment  mF;
45
  private EffectQueueVertex    mV;
43
  private EffectQueueMatrix      mM;
44
  private EffectQueueFragment    mF;
45
  private EffectQueueVertex      mV;
46
  private EffectQueuePostprocess mP;
46 47

  
47
  private boolean matrixCloned, vertexCloned, fragmentCloned;
48
  private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
48 49

  
49 50
///////////////////////////////////////////////////////////////////////////////////////////////////
50 51
    
......
82 83
      mF = new EffectQueueFragment(mID);
83 84
      fragmentCloned = false;
84 85
      }
86

  
87
    if( (flags & Distorted.CLONE_POSTPROCESS) != 0 )
88
      {
89
      mP = d.mP;
90
      postprocessCloned = true;
91
      }
92
    else
93
      {
94
      mP = new EffectQueuePostprocess(mID);
95
      postprocessCloned = false;
96
      }
85 97
    }
86 98

  
87 99
///////////////////////////////////////////////////////////////////////////////////////////////////
88 100
   
89 101
  void drawPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df, long currTime)
90 102
    {
91
    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
92

  
93
    float halfZ = halfInputW*mesh.zFactor;
94

  
95 103
    mM.compute(currTime);
96
    mM.send(df,halfInputW,halfInputH,halfZ);
97
      
98 104
    mV.compute(currTime);
99
    mV.send(halfInputW,halfInputH,halfZ);
100
        
101 105
    mF.compute(currTime);
102
    mF.send(halfInputW,halfInputH);
106
    mP.compute(currTime);
103 107

  
104
    mesh.draw();
108
    float halfZ = halfInputW*mesh.zFactor;
109

  
110
    GLES20.glUseProgram(Distorted.mainProgramH);
111

  
112
    if( mP.mNumEffects==0 )
113
      {
114
      GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
115

  
116
      mM.send(df,halfInputW,halfInputH,halfZ);
117
      mV.send(halfInputW,halfInputH,halfZ);
118
      mF.send(halfInputW,halfInputH);
119

  
120
      mesh.draw();
121
      }
122
    else
123
      {
124
      DistortedFramebuffer fbo = null;
125
      // TODO : set this as output
126

  
127
      // render to the FBO just like above
128
      /*
129
      GLES20.glViewport(0, 0, fbo.mWidth, fbo.mHeight);
130

  
131
      mM.send(fbo,halfInputW,halfInputH,halfZ);
132
      mV.send(halfInputW,halfInputH,halfZ);
133
      mF.send(halfInputW,halfInputH);
134

  
135
      mesh.draw();
136
      */
137

  
138
      GLES20.glUseProgram(Distorted.postProgramH);
139

  
140
      // apply postprocess effects
141
      mP.postprocess(fbo,df);
142
      }
105 143
    }
106 144

  
107 145
///////////////////////////////////////////////////////////////////////////////////////////////////
108 146
   
109
  void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df)
147
  static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df)
110 148
    {
111 149
    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
112 150

  
113
    mM.sendZero(df,halfInputW,halfInputH,halfInputW*mesh.zFactor);
114
    mV.sendZero();
115
    mF.sendZero();
151
    EffectQueueMatrix.sendZero(df,halfInputW,halfInputH,halfInputW*mesh.zFactor);
152
    EffectQueueVertex.sendZero();
153
    EffectQueueFragment.sendZero();
154
    EffectQueuePostprocess.sendZero(2*halfInputW,2*halfInputH);
116 155

  
117 156
    mesh.draw();
118 157
    }
......
121 160
   
122 161
  private void releasePriv()
123 162
    {
124
    if( !matrixCloned  ) mM.abortAll(false);
125
    if( !vertexCloned  ) mV.abortAll(false);
126
    if( !fragmentCloned) mF.abortAll(false);
163
    if( !matrixCloned     ) mM.abortAll(false);
164
    if( !vertexCloned     ) mV.abortAll(false);
165
    if( !fragmentCloned   ) mF.abortAll(false);
166
    if( !postprocessCloned) mP.abortAll(false);
127 167

  
128 168
    mM = null;
129 169
    mV = null;
130 170
    mF = null;
171
    mP = null;
131 172
    }
132 173

  
133 174
///////////////////////////////////////////////////////////////////////////////////////////////////
......
197 238
    mV.registerForMessages(el);
198 239
    mF.registerForMessages(el);
199 240
    mM.registerForMessages(el);
241
    mP.registerForMessages(el);
200 242
    }
201 243

  
202 244
///////////////////////////////////////////////////////////////////////////////////////////////////
......
210 252
    mV.deregisterForMessages(el);
211 253
    mF.deregisterForMessages(el);
212 254
    mM.deregisterForMessages(el);
255
    mP.deregisterForMessages(el);
213 256
    }
214 257

  
215 258
///////////////////////////////////////////////////////////////////////////////////////////////////
......
219 262
 */
220 263
  public int abortAllEffects()
221 264
      {
222
      return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
265
      return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true) + mP.abortAll(true);
223 266
      }
224 267

  
225 268
///////////////////////////////////////////////////////////////////////////////////////////////////
......
233 276
    {
234 277
    switch(type)
235 278
      {
236
      case MATRIX  : return mM.abortAll(true);
237
      case VERTEX  : return mV.abortAll(true);
238
      case FRAGMENT: return mF.abortAll(true);
239
      default      : return 0;
279
      case MATRIX     : return mM.abortAll(true);
280
      case VERTEX     : return mV.abortAll(true);
281
      case FRAGMENT   : return mF.abortAll(true);
282
      case POSTPROCESS: return mP.abortAll(true);
283
      default         : return 0;
240 284
      }
241 285
    }
242 286
    
......
251 295
    {
252 296
    int type = (int)(id&EffectTypes.MASK);
253 297

  
254
    if( type==EffectTypes.MATRIX.type   ) return mM.removeByID(id>>EffectTypes.LENGTH);
255
    if( type==EffectTypes.VERTEX.type   ) return mV.removeByID(id>>EffectTypes.LENGTH);
256
    if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH);
298
    if( type==EffectTypes.MATRIX.type      ) return mM.removeByID(id>>EffectTypes.LENGTH);
299
    if( type==EffectTypes.VERTEX.type      ) return mV.removeByID(id>>EffectTypes.LENGTH);
300
    if( type==EffectTypes.FRAGMENT.type    ) return mF.removeByID(id>>EffectTypes.LENGTH);
301
    if( type==EffectTypes.POSTPROCESS.type ) return mP.removeByID(id>>EffectTypes.LENGTH);
257 302

  
258 303
    return 0;
259 304
    }
......
269 314
    {
270 315
    switch(name.getType())
271 316
      {
272
      case MATRIX  : return mM.removeByType(name);
273
      case VERTEX  : return mV.removeByType(name);
274
      case FRAGMENT: return mF.removeByType(name);
275
      default      : return 0;
317
      case MATRIX     : return mM.removeByType(name);
318
      case VERTEX     : return mV.removeByType(name);
319
      case FRAGMENT   : return mF.removeByType(name);
320
      case POSTPROCESS: return mP.removeByType(name);
321
      default         : return 0;
276 322
      }
277 323
    }
278 324
    
......
288 334
    {
289 335
    int type = (int)(id&EffectTypes.MASK);
290 336

  
291
    if( type==EffectTypes.MATRIX.type   )  return mM.printByID(id>>EffectTypes.LENGTH);
292
    if( type==EffectTypes.VERTEX.type   )  return mV.printByID(id>>EffectTypes.LENGTH);
293
    if( type==EffectTypes.FRAGMENT.type )  return mF.printByID(id>>EffectTypes.LENGTH);
337
    if( type==EffectTypes.MATRIX.type      )  return mM.printByID(id>>EffectTypes.LENGTH);
338
    if( type==EffectTypes.VERTEX.type      )  return mV.printByID(id>>EffectTypes.LENGTH);
339
    if( type==EffectTypes.FRAGMENT.type    )  return mF.printByID(id>>EffectTypes.LENGTH);
340
    if( type==EffectTypes.POSTPROCESS.type )  return mP.printByID(id>>EffectTypes.LENGTH);
294 341

  
295 342
    return false;
296 343
    }
......
864 911
    {
865 912
    return mV.add(EffectNames.WAVE, wave, center, region);
866 913
    }
914

  
915
///////////////////////////////////////////////////////////////////////////////////////////////////
916
// Postprocess-based effects
917
///////////////////////////////////////////////////////////////////////////////////////////////////
918
/**
919
 * Blur the object.
920
 *
921
 * @param radius The 'strength' if the effect, in pixels. 0 = no blur, 10 = when blurring a given pixel,
922
 *               take into account 10 pixels in each direction.
923
 * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
924
 * @return ID of the effect added, or -1 if we failed to add one.
925
 */
926
  public long blur(Data1D radius, Data2D center)
927
    {
928
    return mP.add(EffectNames.BLUR, radius, center);
929
    }
867 930
  }
src/main/java/org/distorted/library/DistortedFramebuffer.java
243 243
///////////////////////////////////////////////////////////////////////////////////////////////////
244 244
// must be called form a thread holding OpenGL Context
245 245

  
246
  static synchronized void deleteAllMarked()
246
  private static synchronized void deleteAllMarked()
247 247
    {
248 248
    if( mListMarked )
249 249
      {
src/main/java/org/distorted/library/DistortedTree.java
222 222
        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
223 223

  
224 224
        if( mTexture.setAsInput() )
225
          mEffects.drawNoEffectsPriv(mTexture.mHalfX, mTexture.mHalfY, mMesh, mData.mFBO);
225
          DistortedEffects.drawNoEffectsPriv(mTexture.mHalfX, mTexture.mHalfY, mMesh, mData.mFBO);
226 226

  
227 227
        synchronized(this)
228 228
          {
src/main/java/org/distorted/library/EffectQueueFragment.java
134 134

  
135 135
///////////////////////////////////////////////////////////////////////////////////////////////////
136 136

  
137
  synchronized void sendZero() 
137
  synchronized static void sendZero()
138 138
    {
139 139
    GLES20.glUniform1i( mNumEffectsH, 0);
140 140
    }
src/main/java/org/distorted/library/EffectQueueMatrix.java
257 257
///////////////////////////////////////////////////////////////////////////////////////////////////
258 258
// here construct the ModelView Matrix, but without any effects
259 259

  
260
  synchronized void sendZero(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
260
  synchronized static void sendZero(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
261 261
    {
262 262
    Matrix.setIdentityM(mTmpMatrix, 0);
263 263
    Matrix.translateM(mTmpMatrix, 0, halfX-df.mWidth/2, df.mHeight/2-halfY, -df.mDistance);
src/main/java/org/distorted/library/EffectQueuePostprocess.java
98 98
    mTime = currTime;  
99 99
    }  
100 100

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

  
103
  void postprocess(DistortedFramebuffer input, DistortedFramebuffer output)
104
    {
105
    // TODO
106
    }
107

  
101 108
///////////////////////////////////////////////////////////////////////////////////////////////////
102 109

  
103 110
  protected void moveEffect(int index)
......
121 128
      }
122 129
    }
123 130

  
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

  
133
  synchronized static void sendZero(float objX, float objY)
134
    {
135
    GLES20.glUniform1i( mNumEffectsH, 0);
136
    GLES20.glUniform2f( mObjDH , objX, objY);
137
    }
138

  
124 139
///////////////////////////////////////////////////////////////////////////////////////////////////
125 140
// blur
126 141

  
src/main/java/org/distorted/library/EffectQueueVertex.java
153 153

  
154 154
///////////////////////////////////////////////////////////////////////////////////////////////////
155 155

  
156
  synchronized void sendZero() 
156
  synchronized static void sendZero()
157 157
    {
158 158
    GLES20.glUniform1i( mNumEffectsH, 0);
159 159
    }
src/main/res/raw/post_fragment_shader.glsl
17 17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                       //
18 18
//////////////////////////////////////////////////////////////////////////////////////////////
19 19

  
20
varying vec2 vTexCoordinate;
20
#define NUM_POSTPROCESS 3
21
#define BLUR 0
22

  
23
precision lowp float;
24

  
25
varying vec2 v_TexCoordinate;
21 26
uniform sampler2D u_Texture;
22 27
uniform vec2 u_objD;
23
uniform int fNumEffects;                   // total number of postprocessing effects
28
uniform int pNumEffects;                   // total number of postprocessing effects
24 29

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

  
30 34
//////////////////////////////////////////////////////////////////////////////////////////////
31 35
// BLUR EFFECT
32 36

  
33
void blur(out vec4 color)
37
void blur(out vec4 pixel)
34 38
  {
35
  color = vec4(0.0);
39
  pixel = vec4(0.0);
36 40

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

  
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;
44
  for (float x = -4.0; x <= 4.0; x+=1.0)
45
    for (float y = -4.0; y <= 4.0; y+=1.0)
46
      {
47
      pixel += texture2D( u_Texture, vec2(v_TexCoordinate.x + x * blurSizeH, v_TexCoordinate.y + y * blurSizeV) ) / 81.0;
48
      }
43 49
  }
44 50

  
45 51
#endif
......
51 57
  vec4 pixel = texture2D(u_Texture,v_TexCoordinate);
52 58

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

Also available in: Unified diff