Project

General

Profile

Download (22 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / main / DistortedEffects.java @ e6519ac8

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.main;
21

    
22
import android.content.res.Resources;
23
import android.opengl.GLES31;
24
import android.util.Log;
25

    
26
import org.distorted.library.R;
27
import org.distorted.library.effect.Effect;
28
import org.distorted.library.effect.EffectName;
29
import org.distorted.library.effect.EffectType;
30
import org.distorted.library.effect.FragmentEffect;
31
import org.distorted.library.effect.VertexEffect;
32
import org.distorted.library.message.EffectListener;
33
import org.distorted.library.program.DistortedProgram;
34
import org.distorted.library.program.FragmentCompilationException;
35
import org.distorted.library.program.FragmentUniformsException;
36
import org.distorted.library.program.LinkingException;
37
import org.distorted.library.program.VertexCompilationException;
38
import org.distorted.library.program.VertexUniformsException;
39

    
40
import java.io.InputStream;
41
import java.nio.ByteBuffer;
42
import java.nio.ByteOrder;
43
import java.nio.FloatBuffer;
44

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46
/**
47
 * Class containing Matrix, Vertex, Fragment and Postprocessing effect queues.
48
 * <p>
49
 * The queues hold actual effects to be applied to a given (InputSurface,MeshObject) combo.
50
 */
51
public class DistortedEffects
52
  {
53
  /// MAIN PROGRAM ///
54
  private static DistortedProgram mMainProgram;
55
  private static int mMainTextureH;
56

    
57
  /// BLIT PROGRAM ///
58
  private static DistortedProgram mBlitProgram;
59
  private static int mBlitTextureH;
60
  private static int mBlitDepthH;
61
  private static final FloatBuffer mQuadPositions;
62

    
63
  static
64
    {
65
    float[] positionData= { -0.5f, -0.5f,  -0.5f, 0.5f,  0.5f,-0.5f,  0.5f, 0.5f };
66
    mQuadPositions = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()).asFloatBuffer();
67
    mQuadPositions.put(positionData).position(0);
68
    }
69

    
70
  /// BLIT DEPTH PROGRAM ///
71
  private static DistortedProgram mBlitDepthProgram;
72
  private static int mBlitDepthTextureH;
73
  private static int mBlitDepthDepthTextureH;
74
  private static int mBlitDepthDepthH;
75

    
76
  /// NORMAL PROGRAM /////
77
  private static DistortedProgram mNormalProgram;
78
  private static int mNormalMVPMatrixH;
79
  /// END PROGRAMS //////
80

    
81
  private static long mNextID =0;
82
  private long mID;
83

    
84
  private EffectQueueMatrix mM;
85
  private EffectQueueFragment mF;
86
  private EffectQueueVertex mV;
87
  private EffectQueuePostprocess mP;
88

    
89
  private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
90

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

    
93
  static void createProgram(Resources resources)
94
  throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
95
    {
96
    // MAIN PROGRAM ////////////////////////////////////
97
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
98
    final InputStream mainFragStream = resources.openRawResource(R.raw.main_fragment_shader);
99

    
100
    int numF = FragmentEffect.getNumEnabled();
101
    int numV = VertexEffect.getNumEnabled();
102

    
103
    String mainVertHeader= Distorted.GLSL_VERSION + ("#define NUM_VERTEX "   + ( numV>0 ? getMax(EffectType.VERTEX  ) : 0 ) + "\n");
104
    String mainFragHeader= Distorted.GLSL_VERSION + ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n");
105
    String enabledEffectV= VertexEffect.getGLSL();
106
    String enabledEffectF= FragmentEffect.getGLSL();
107

    
108
    //android.util.Log.e("Effects", "vertHeader= "+mainVertHeader);
109
    //android.util.Log.e("Effects", "fragHeader= "+mainFragHeader);
110
    //android.util.Log.e("Effects", "enabledV= "+enabledEffectV);
111
    //android.util.Log.e("Effects", "enabledF= "+enabledEffectF);
112

    
113
    String[] feedback = { "v_Position", "v_endPosition" };
114

    
115
    mMainProgram = new DistortedProgram( mainVertStream, mainFragStream, mainVertHeader, mainFragHeader,
116
                                         enabledEffectV, enabledEffectF, Distorted.GLSL, feedback);
117

    
118
    int mainProgramH = mMainProgram.getProgramHandle();
119
    EffectQueueFragment.getUniforms(mainProgramH);
120
    EffectQueueVertex.getUniforms(mainProgramH);
121
    EffectQueueMatrix.getUniforms(mainProgramH);
122
    mMainTextureH= GLES31.glGetUniformLocation( mainProgramH, "u_Texture");
123

    
124
    // BLIT PROGRAM ////////////////////////////////////
125
    final InputStream blitVertStream = resources.openRawResource(R.raw.blit_vertex_shader);
126
    final InputStream blitFragStream = resources.openRawResource(R.raw.blit_fragment_shader);
127

    
128
    String blitVertHeader= (Distorted.GLSL_VERSION + "#define NUM_VERTEX 0\n"  );
129
    String blitFragHeader= (Distorted.GLSL_VERSION + "#define NUM_FRAGMENT 0\n");
130

    
131
    try
132
      {
133
      mBlitProgram = new DistortedProgram(blitVertStream,blitFragStream,blitVertHeader,blitFragHeader, Distorted.GLSL);
134
      }
135
    catch(Exception e)
136
      {
137
      Log.e("EFFECTS", "exception trying to compile BLIT program: "+e.getMessage());
138
      throw new RuntimeException(e.getMessage());
139
      }
140

    
141
    int blitProgramH = mBlitProgram.getProgramHandle();
142
    mBlitTextureH  = GLES31.glGetUniformLocation( blitProgramH, "u_Texture");
143
    mBlitDepthH    = GLES31.glGetUniformLocation( blitProgramH, "u_Depth");
144

    
145
    // BLIT DEPTH PROGRAM ////////////////////////////////////
146
    final InputStream blitDepthVertStream = resources.openRawResource(R.raw.blit_depth_vertex_shader);
147
    final InputStream blitDepthFragStream = resources.openRawResource(R.raw.blit_depth_fragment_shader);
148

    
149
    try
150
      {
151
      mBlitDepthProgram = new DistortedProgram(blitDepthVertStream,blitDepthFragStream,blitVertHeader,blitFragHeader, Distorted.GLSL);
152
      }
153
    catch(Exception e)
154
      {
155
      Log.e("EFFECTS", "exception trying to compile BLIT DEPTH program: "+e.getMessage());
156
      throw new RuntimeException(e.getMessage());
157
      }
158

    
159
    int blitDepthProgramH   = mBlitDepthProgram.getProgramHandle();
160
    mBlitDepthTextureH      = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Texture");
161
    mBlitDepthDepthTextureH = GLES31.glGetUniformLocation( blitDepthProgramH, "u_DepthTexture");
162
    mBlitDepthDepthH        = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Depth");
163

    
164
    // NORMAL PROGRAM //////////////////////////////////////
165
    final InputStream normalVertexStream   = resources.openRawResource(R.raw.normal_vertex_shader);
166
    final InputStream normalFragmentStream = resources.openRawResource(R.raw.normal_fragment_shader);
167

    
168
    try
169
      {
170
      mNormalProgram = new DistortedProgram(normalVertexStream,normalFragmentStream, Distorted.GLSL_VERSION, Distorted.GLSL_VERSION, Distorted.GLSL);
171
      }
172
    catch(Exception e)
173
      {
174
      Log.e("EFFECTS", "exception trying to compile NORMAL program: "+e.getMessage());
175
      throw new RuntimeException(e.getMessage());
176
      }
177

    
178
    int normalProgramH = mNormalProgram.getProgramHandle();
179
    mNormalMVPMatrixH  = GLES31.glGetUniformLocation( normalProgramH, "u_MVPMatrix");
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  private void initializeEffectLists(DistortedEffects d, int flags)
185
    {
186
    if( (flags & Distorted.CLONE_MATRIX) != 0 )
187
      {
188
      mM = d.mM;
189
      matrixCloned = true;
190
      }
191
    else
192
      {
193
      mM = new EffectQueueMatrix(mID);
194
      matrixCloned = false;
195
      }
196
    
197
    if( (flags & Distorted.CLONE_VERTEX) != 0 )
198
      {
199
      mV = d.mV;
200
      vertexCloned = true;
201
      }
202
    else
203
      {
204
      mV = new EffectQueueVertex(mID);
205
      vertexCloned = false;
206
      }
207
    
208
    if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
209
      {
210
      mF = d.mF;
211
      fragmentCloned = true;
212
      }
213
    else
214
      {
215
      mF = new EffectQueueFragment(mID);
216
      fragmentCloned = false;
217
      }
218

    
219
    if( (flags & Distorted.CLONE_POSTPROCESS) != 0 )
220
      {
221
      mP = d.mP;
222
      postprocessCloned = true;
223
      }
224
    else
225
      {
226
      mP = new EffectQueuePostprocess(mID);
227
      postprocessCloned = false;
228
      }
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  EffectQueuePostprocess getPostprocess()
234
    {
235
    return mP;
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  void newNode(DistortedNode node)
241
    {
242
    mM.newNode(node);
243
    mF.newNode(node);
244
    mV.newNode(node);
245
    mP.newNode(node);
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  private void displayNormals(MeshObject mesh)
251
    {
252
    GLES31.glBindBufferBase(GLES31.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mesh.mAttTFO[0]);
253
    GLES31.glBeginTransformFeedback( GLES31.GL_POINTS);
254
    DistortedRenderState.switchOffDrawing();
255
    GLES31.glDrawArrays( GLES31.GL_POINTS, 0, mesh.numVertices);
256
    DistortedRenderState.restoreDrawing();
257
    GLES31.glEndTransformFeedback();
258
    GLES31.glBindBufferBase(GLES31.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
259

    
260
    mNormalProgram.useProgram();
261
    GLES31.glUniformMatrix4fv(mNormalMVPMatrixH, 1, false, mM.getMVP() , 0);
262
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttTFO[0]);
263
    GLES31.glVertexAttribPointer(mNormalProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, 0, 0);
264
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
265
    GLES31.glLineWidth(8.0f);
266
    GLES31.glDrawArrays(GLES31.GL_LINES, 0, 2*mesh.numVertices);
267
    }
268

    
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

    
271
  void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime, float marginInPixels)
272
    {
273
    float halfZ = halfW*mesh.zFactor;
274

    
275
    mM.compute(currTime);
276
    mV.compute(currTime,halfW,halfH,halfZ);
277
    mF.compute(currTime,halfW,halfH);
278
    mP.compute(currTime);
279

    
280
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
281

    
282
    mMainProgram.useProgram();
283
    GLES31.glUniform1i(mMainTextureH, 0);
284

    
285
    if( Distorted.GLSL >= 300 )
286
      {
287
      GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttVBO[0]);
288
      GLES31.glVertexAttribPointer(mMainProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET0);
289
      GLES31.glVertexAttribPointer(mMainProgram.mAttribute[1], MeshObject.NOR_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET1);
290
      GLES31.glVertexAttribPointer(mMainProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET2);
291
      GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
292
      }
293
    else
294
      {
295
      mesh.mVertAttribs.position(0);
296
      GLES31.glVertexAttribPointer(mMainProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, mesh.mVertAttribs);
297
      mesh.mVertAttribs.position(MeshObject.POS_DATA_SIZE);
298
      GLES31.glVertexAttribPointer(mMainProgram.mAttribute[1], MeshObject.NOR_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, mesh.mVertAttribs);
299
      mesh.mVertAttribs.position(MeshObject.POS_DATA_SIZE+MeshObject.NOR_DATA_SIZE);
300
      GLES31.glVertexAttribPointer(mMainProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, mesh.mVertAttribs);
301
      }
302

    
303
    mM.send(surface,halfW,halfH,halfZ,marginInPixels);
304
    mV.send();
305
    mF.send();
306

    
307
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
308

    
309
    if( mesh.mShowNormals ) displayNormals(mesh);
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313
/**
314
 * Only for use by the library itself.
315
 *
316
 * @y.exclude
317
 */
318
  public static void blitPriv(DistortedOutputSurface surface)
319
    {
320
    mBlitProgram.useProgram();
321

    
322
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
323
    GLES31.glUniform1i(mBlitTextureH, 0);
324
    GLES31.glUniform1f( mBlitDepthH , 1.0f-surface.mNear);
325
    GLES31.glVertexAttribPointer(mBlitProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
326
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
327
    }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330

    
331
  static void blitDepthPriv(DistortedOutputSurface surface)
332
    {
333
    mBlitDepthProgram.useProgram();
334

    
335
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
336
    GLES31.glUniform1i(mBlitDepthTextureH, 0);
337
    GLES31.glUniform1i(mBlitDepthDepthTextureH, 1);
338
    GLES31.glUniform1f( mBlitDepthDepthH , 1.0f-surface.mNear);
339
    GLES31.glVertexAttribPointer(mBlitDepthProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
340
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344
   
345
  private void releasePriv()
346
    {
347
    if( !matrixCloned   )   mM.abortAll(false);
348
    if( !vertexCloned   )   mV.abortAll(false);
349
    if( !fragmentCloned )   mF.abortAll(false);
350
    if( !postprocessCloned) mP.abortAll(false);
351

    
352
    mM = null;
353
    mV = null;
354
    mF = null;
355
    mP = null;
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
  static void onDestroy()
361
    {
362
    mNextID = 0;
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366
// PUBLIC API
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368
/**
369
 * Create empty effect queue.
370
 */
371
  public DistortedEffects()
372
    {
373
    mID = ++mNextID;
374
    initializeEffectLists(this,0);
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378
/**
379
 * Copy constructor.
380
 * <p>
381
 * Whatever we do not clone gets created just like in the default constructor.
382
 *
383
 * @param dc    Source object to create our object from
384
 * @param flags A bitmask of values specifying what to copy.
385
 *              For example, CLONE_VERTEX | CLONE_MATRIX.
386
 */
387
  public DistortedEffects(DistortedEffects dc, int flags)
388
    {
389
    mID = ++mNextID;
390
    initializeEffectLists(dc,flags);
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394
/**
395
 * Releases all resources. After this call, the queue should not be used anymore.
396
 */
397
  @SuppressWarnings("unused")
398
  public synchronized void delete()
399
    {
400
    releasePriv();
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404
/**
405
 * Returns unique ID of this instance.
406
 *
407
 * @return ID of the object.
408
 */
409
  public long getID()
410
      {
411
      return mID;
412
      }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415
/**
416
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
417
 * to one of the Effects in our queues. Nothing will happen if 'el' is already in the list.
418
 * 
419
 * @param el A class implementing the EffectListener interface that wants to get notifications.
420
 */
421
  @SuppressWarnings("unused")
422
  public void registerForMessages(EffectListener el)
423
    {
424
    mM.registerForMessages(el);
425
    mV.registerForMessages(el);
426
    mF.registerForMessages(el);
427
    mP.registerForMessages(el);
428
    }
429

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431
/**
432
 * Removes the calling class from the list of Listeners that get notified if something happens to Effects in our queue.
433
 * 
434
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
435
 */
436
  @SuppressWarnings("unused")
437
  public void deregisterForMessages(EffectListener el)
438
    {
439
    mM.deregisterForMessages(el);
440
    mV.deregisterForMessages(el);
441
    mF.deregisterForMessages(el);
442
    mP.deregisterForMessages(el);
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446
/**
447
 * Aborts all Effects.
448
 * @return Number of effects aborted.
449
 */
450
  public int abortAllEffects()
451
    {
452
    return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
453
    }
454

    
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456
/**
457
 * Aborts all Effects of a given type, for example all MATRIX Effects.
458
 * 
459
 * @param type one of the constants defined in {@link EffectType}
460
 * @return Number of effects aborted.
461
 */
462
  public int abortByType(EffectType type)
463
    {
464
    switch(type)
465
      {
466
      case MATRIX     : return mM.abortAll(true);
467
      case VERTEX     : return mV.abortAll(true);
468
      case FRAGMENT   : return mF.abortAll(true);
469
      case POSTPROCESS: return mP.abortAll(true);
470
      default         : return 0;
471
      }
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475
/**
476
 * Aborts an Effect by its ID.
477
 *
478
 * @param id the Id of the Effect to be removed, as returned by getID().
479
 * @return Number of effects aborted.
480
 */
481
  public int abortById(long id)
482
    {
483
    long type = id&EffectType.MASK;
484

    
485
    if( type == EffectType.MATRIX.ordinal()      ) return mM.removeById(id);
486
    if( type == EffectType.VERTEX.ordinal()      ) return mV.removeById(id);
487
    if( type == EffectType.FRAGMENT.ordinal()    ) return mF.removeById(id);
488
    if( type == EffectType.POSTPROCESS.ordinal() ) return mP.removeById(id);
489

    
490
    return 0;
491
    }
492

    
493
///////////////////////////////////////////////////////////////////////////////////////////////////
494
/**
495
 * Aborts a single Effect.
496
 * 
497
 * @param effect the Effect we want to abort.
498
 * @return number of Effects aborted. Always either 0 or 1.
499
 */
500
  public int abortEffect(Effect effect)
501
    {
502
    switch(effect.getType())
503
      {
504
      case MATRIX     : return mM.removeEffect(effect);
505
      case VERTEX     : return mV.removeEffect(effect);
506
      case FRAGMENT   : return mF.removeEffect(effect);
507
      case POSTPROCESS: return mP.removeEffect(effect);
508
      default         : return 0;
509
      }
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513
/**
514
 * Abort all Effects of a given name, for example all rotations.
515
 * 
516
 * @param name one of the constants defined in {@link EffectName}
517
 * @return number of Effects aborted.
518
 */
519
  public int abortByName(EffectName name)
520
    {
521
    switch(name.getType())
522
      {
523
      case MATRIX     : return mM.removeByName(name);
524
      case VERTEX     : return mV.removeByName(name);
525
      case FRAGMENT   : return mF.removeByName(name);
526
      case POSTPROCESS: return mP.removeByName(name);
527
      default                : return 0;
528
      }
529
    }
530

    
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532
/**
533
 * Returns the maximum number of effects of a given type that can be simultaneously applied to a
534
 * single (InputSurface,MeshObject) combo.
535
 *
536
 * @param type {@link EffectType}
537
 * @return The maximum number of effects of a given type.
538
 */
539
  @SuppressWarnings("unused")
540
  public static int getMax(EffectType type)
541
    {
542
    return EffectQueue.getMax(type.ordinal());
543
    }
544

    
545
///////////////////////////////////////////////////////////////////////////////////////////////////
546
/**
547
 * Sets the maximum number of effects that can be stored in a single EffectQueue at one time.
548
 * This can fail if:
549
 * <ul>
550
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
551
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
552
 *     before the Vertex Shader gets compiled, i.e. before the call to {@link Distorted#onCreate}. After this
553
 *     time only decreasing the value of 'max' is permitted.
554
 * <li>Furthermore, this needs to be called before any instances of the DistortedEffects class get created.
555
 * </ul>
556
 *
557
 * @param type {@link EffectType}
558
 * @param max new maximum number of simultaneous effects. Has to be a non-negative number not greater
559
 *            than Byte.MAX_VALUE
560
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
561
 */
562
  @SuppressWarnings("unused")
563
  public static boolean setMax(EffectType type, int max)
564
    {
565
    return EffectQueue.setMax(type.ordinal(),max);
566
    }
567

    
568
///////////////////////////////////////////////////////////////////////////////////////////////////
569
/**
570
 * Add a new Effect to our queue.
571
 *
572
 * @param effect The Effect to add.
573
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
574
 */
575
  public boolean apply(Effect effect)
576
    {
577
    switch(effect.getType())
578
      {
579
      case MATRIX      : return mM.add(effect);
580
      case VERTEX      : return mV.add(effect);
581
      case FRAGMENT    : return mF.add(effect);
582
      case POSTPROCESS : return mP.add(effect);
583
      }
584

    
585
    return false;
586
    }
587
  }
(2-2/22)