Project

General

Profile

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

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

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.GLES30;
24

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

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

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

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

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

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

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

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

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

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

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

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

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

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

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

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

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

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

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

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

    
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

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

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

    
279
    GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight );
280

    
281
    mMainProgram.useProgram();
282
    GLES30.glUniform1i(mMainTextureH, 0);
283

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

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

    
306
    GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
307

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

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

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

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

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

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

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

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

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

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

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

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

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

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

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

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

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

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

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

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

    
489
    return 0;
490
    }
491

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

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

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

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

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

    
584
    return false;
585
    }
586
  }
(2-2/21)