Project

General

Profile

« Previous | Next » 

Revision 13687207

Added by Leszek Koltunski about 7 years ago

Separate the Postprocessing Effects to their own DistortedEffectsPostprocess queue.
This partly breaks Multiblur (to be debugged)

View differences:

src/main/java/org/distorted/library/DistortedEffects.java
44 44

  
45 45
///////////////////////////////////////////////////////////////////////////////////////////////////
46 46
/**
47
 * Class containing {@link EffectTypes#LENGTH} queues, each a class derived from EffectQueue.
47
 * Class containing Matrix,Vertex and Fragment effect queues. Postprocessing queue is held in a separate
48
 * class.
48 49
 * <p>
49 50
 * The queues hold actual effects to be applied to a given (DistortedTexture,MeshObject) combo.
50 51
 */
......
98 99
  private EffectQueueMatrix      mM;
99 100
  private EffectQueueFragment    mF;
100 101
  private EffectQueueVertex      mV;
101
  private EffectQueuePostprocess mP;
102 102

  
103
  private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
103
  private boolean matrixCloned, vertexCloned, fragmentCloned;
104 104

  
105 105
///////////////////////////////////////////////////////////////////////////////////////////////////
106 106

  
......
229 229
      mF = new EffectQueueFragment(mID);
230 230
      fragmentCloned = false;
231 231
      }
232

  
233
    if( (flags & Distorted.CLONE_POSTPROCESS) != 0 )
234
      {
235
      mP = d.mP;
236
      postprocessCloned = true;
237
      }
238
    else
239
      {
240
      mP = new EffectQueuePostprocess(mID);
241
      postprocessCloned = false;
242
      }
243 232
    }
244 233

  
245 234
///////////////////////////////////////////////////////////////////////////////////////////////////
......
295 284
    GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
296 285
    }
297 286

  
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

  
300
  EffectQueuePostprocess getPostprocess()
301
    {
302
    return mP;
303
    }
304

  
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

  
307
  int postprocessPriv(long currTime, DistortedOutputSurface surface)
308
    {
309
    return mP.postprocess(currTime,surface);
310
    }
311

  
312 287
///////////////////////////////////////////////////////////////////////////////////////////////////
313 288

  
314 289
  void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime)
......
356 331
    if( !matrixCloned     ) mM.abortAll(false);
357 332
    if( !vertexCloned     ) mV.abortAll(false);
358 333
    if( !fragmentCloned   ) mF.abortAll(false);
359
    if( !postprocessCloned) mP.abortAll(false);
360 334

  
361 335
    mM = null;
362 336
    mV = null;
363 337
    mF = null;
364
    mP = null;
365 338
    }
366 339

  
367 340
///////////////////////////////////////////////////////////////////////////////////////////////////
......
410 383
/**
411 384
 * Releases all resources. After this call, the queue should not be used anymore.
412 385
 */
386
  @SuppressWarnings("unused")
413 387
  public synchronized void delete()
414 388
    {
415 389
    releasePriv();
......
433 407
 * 
434 408
 * @param el A class implementing the EffectListener interface that wants to get notifications.
435 409
 */
410
  @SuppressWarnings("unused")
436 411
  public void registerForMessages(EffectListener el)
437 412
    {
438 413
    mV.registerForMessages(el);
439 414
    mF.registerForMessages(el);
440 415
    mM.registerForMessages(el);
441
    mP.registerForMessages(el);
442 416
    }
443 417

  
444 418
///////////////////////////////////////////////////////////////////////////////////////////////////
......
447 421
 * 
448 422
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
449 423
 */
424
  @SuppressWarnings("unused")
450 425
  public void deregisterForMessages(EffectListener el)
451 426
    {
452 427
    mV.deregisterForMessages(el);
453 428
    mF.deregisterForMessages(el);
454 429
    mM.deregisterForMessages(el);
455
    mP.deregisterForMessages(el);
456 430
    }
457 431

  
458 432
///////////////////////////////////////////////////////////////////////////////////////////////////
......
461 435
 * @return Number of effects aborted.
462 436
 */
463 437
  public int abortAllEffects()
464
      {
465
      return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true) + mP.abortAll(true);
466
      }
438
    {
439
    return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
440
    }
467 441

  
468 442
///////////////////////////////////////////////////////////////////////////////////////////////////
469 443
/**
......
479 453
      case MATRIX     : return mM.abortAll(true);
480 454
      case VERTEX     : return mV.abortAll(true);
481 455
      case FRAGMENT   : return mF.abortAll(true);
482
      case POSTPROCESS: return mP.abortAll(true);
483 456
      default         : return 0;
484 457
      }
485 458
    }
......
498 471
    if( type==EffectTypes.MATRIX.type      ) return mM.removeByID(id>>EffectTypes.LENGTH);
499 472
    if( type==EffectTypes.VERTEX.type      ) return mV.removeByID(id>>EffectTypes.LENGTH);
500 473
    if( type==EffectTypes.FRAGMENT.type    ) return mF.removeByID(id>>EffectTypes.LENGTH);
501
    if( type==EffectTypes.POSTPROCESS.type ) return mP.removeByID(id>>EffectTypes.LENGTH);
502 474

  
503 475
    return 0;
504 476
    }
......
517 489
      case MATRIX     : return mM.removeByType(name);
518 490
      case VERTEX     : return mV.removeByType(name);
519 491
      case FRAGMENT   : return mF.removeByType(name);
520
      case POSTPROCESS: return mP.removeByType(name);
521 492
      default         : return 0;
522 493
      }
523 494
    }
......
529 500
 * @param id Effect ID we want to print info about
530 501
 * @return <code>true</code> if a single Effect of type effectType has been found.
531 502
 */
532
    
503
  @SuppressWarnings("unused")
533 504
  public boolean printEffect(long id)
534 505
    {
535 506
    int type = (int)(id&EffectTypes.MASK);
536 507

  
537
    if( type==EffectTypes.MATRIX.type      )  return mM.printByID(id>>EffectTypes.LENGTH);
538
    if( type==EffectTypes.VERTEX.type      )  return mV.printByID(id>>EffectTypes.LENGTH);
539
    if( type==EffectTypes.FRAGMENT.type    )  return mF.printByID(id>>EffectTypes.LENGTH);
540
    if( type==EffectTypes.POSTPROCESS.type )  return mP.printByID(id>>EffectTypes.LENGTH);
508
    if( type==EffectTypes.MATRIX.type  )  return mM.printByID(id>>EffectTypes.LENGTH);
509
    if( type==EffectTypes.VERTEX.type  )  return mV.printByID(id>>EffectTypes.LENGTH);
510
    if( type==EffectTypes.FRAGMENT.type)  return mF.printByID(id>>EffectTypes.LENGTH);
541 511

  
542 512
    return false;
543 513
    }
......
563 533
 *
564 534
 * @return The maximum number of Matrix effects
565 535
 */
536
  @SuppressWarnings("unused")
566 537
  public static int getMaxMatrix()
567 538
    {
568 539
    return EffectQueue.getMax(EffectTypes.MATRIX.ordinal());
......
574 545
 *
575 546
 * @return The maximum number of Vertex effects
576 547
 */
548
  @SuppressWarnings("unused")
577 549
  public static int getMaxVertex()
578 550
    {
579 551
    return EffectQueue.getMax(EffectTypes.VERTEX.ordinal());
......
585 557
 *
586 558
 * @return The maximum number of Fragment effects
587 559
 */
560
  @SuppressWarnings("unused")
588 561
  public static int getMaxFragment()
589 562
    {
590 563
    return EffectQueue.getMax(EffectTypes.FRAGMENT.ordinal());
591 564
    }
592 565

  
593
///////////////////////////////////////////////////////////////////////////////////////////////////
594
/**
595
 * Returns the maximum number of Postprocess effects.
596
 *
597
 * @return The maximum number of Postprocess effects
598
 */
599
  public static int getMaxPostprocess()
600
    {
601
    return EffectQueue.getMax(EffectTypes.POSTPROCESS.ordinal());
602
    }
603

  
604 566
///////////////////////////////////////////////////////////////////////////////////////////////////
605 567
/**
606 568
 * Sets the maximum number of Matrix effects that can be stored in a single EffectQueue at one time.
......
617 579
 *            than Byte.MAX_VALUE
618 580
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
619 581
 */
582
  @SuppressWarnings("unused")
620 583
  public static boolean setMaxMatrix(int max)
621 584
    {
622 585
    return EffectQueue.setMax(EffectTypes.MATRIX.ordinal(),max);
......
638 601
 *            than Byte.MAX_VALUE
639 602
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
640 603
 */
604
  @SuppressWarnings("unused")
641 605
  public static boolean setMaxVertex(int max)
642 606
    {
643 607
    return EffectQueue.setMax(EffectTypes.VERTEX.ordinal(),max);
......
659 623
 *            than Byte.MAX_VALUE
660 624
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
661 625
 */
626
  @SuppressWarnings("unused")
662 627
  public static boolean setMaxFragment(int max)
663 628
    {
664 629
    return EffectQueue.setMax(EffectTypes.FRAGMENT.ordinal(),max);
665 630
    }
666 631

  
667
///////////////////////////////////////////////////////////////////////////////////////////////////
668
/**
669
 * Sets the maximum number of Postprocess effects that can be stored in a single EffectQueue at one time.
670
 * This can fail if:
671
 * <ul>
672
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
673
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
674
 *     before the Fragment Shader gets compiled, i.e. before the call to {@link Distorted#onCreate}. After this
675
 *     time only decreasing the value of 'max' is permitted.
676
 * <li>Furthermore, this needs to be called before any instances of the DistortedEffects class get created.
677
 * </ul>
678
 *
679
 * @param max new maximum number of simultaneous Postprocess Effects. Has to be a non-negative number not greater
680
 *            than Byte.MAX_VALUE
681
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
682
 */
683
  public static boolean setMaxPostprocess(int max)
684
    {
685
    return EffectQueue.setMax(EffectTypes.POSTPROCESS.ordinal(),max);
686
    }
687

  
688 632
///////////////////////////////////////////////////////////////////////////////////////////////////   
689 633
///////////////////////////////////////////////////////////////////////////////////////////////////
690 634
// Individual effect functions.
......
1126 1070
    {
1127 1071
    return mV.add(EffectNames.WAVE, wave, center, region);
1128 1072
    }
1129

  
1130
///////////////////////////////////////////////////////////////////////////////////////////////////
1131
// Postprocess-based effects
1132
///////////////////////////////////////////////////////////////////////////////////////////////////
1133
/**
1134
 * Blur the object.
1135
 *
1136
 * @param radius The 'strength' if the effect, in pixels. 0 = no blur, 10 = when blurring a given pixel,
1137
 *               take into account 10 pixels in each direction.
1138
 * @return ID of the effect added, or -1 if we failed to add one.
1139
 */
1140
  public long blur(Data1D radius)
1141
    {
1142
    return mP.add(EffectNames.BLUR, radius);
1143
    }
1144 1073
  }
src/main/java/org/distorted/library/DistortedEffectsPostprocess.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 org.distorted.library.message.EffectListener;
23
import org.distorted.library.type.Data1D;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

  
27
/**
28
 * Class containing the queue of postprocessing effects.
29
 * <p>
30
 * This better be separate from the main DistortedEffects class, because we want to be able to apply
31
 * the same postprocessing effects (i.e. not only the same effects, but the very same instance of this
32
 * object) to several Children of a Node. Reason for that: if several children have the same Object,
33
 * it is easy to group them into 'Buckets' where each bucket has the same postprocessing effects and
34
 * is therefore rendered to the same buffer, which is then postprocessed in one go.
35
 * <p>
36
 * The queue holds actual effects to be applied to a given bucket of several (DistortedTexture,MeshObject) combos.
37
 */
38
public class DistortedEffectsPostprocess
39
  {
40
  private static long mNextID =0;
41
  private long mID;
42

  
43
  private EffectQueuePostprocess mP;
44

  
45
  private boolean postprocessCloned;
46

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

  
49
  private void initializeEffectLists(DistortedEffectsPostprocess d, int flags)
50
    {
51
    if( (flags & Distorted.CLONE_POSTPROCESS) != 0 )
52
      {
53
      mP = d.mP;
54
      postprocessCloned = true;
55
      }
56
    else
57
      {
58
      mP = new EffectQueuePostprocess(mID);
59
      postprocessCloned = false;
60
      }
61
    }
62

  
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

  
65
  EffectQueuePostprocess getPostprocess()
66
    {
67
    return mP;
68
    }
69

  
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

  
72
  int postprocessPriv(long currTime, DistortedOutputSurface surface)
73
    {
74
    return mP.postprocess(currTime,surface);
75
    }
76

  
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

  
79
  private void releasePriv()
80
    {
81
    if( !postprocessCloned) mP.abortAll(false);
82

  
83
    mP = null;
84
    }
85

  
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87
// PUBLIC API
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89
/**
90
 * Create empty effect queue.
91
 */
92
  public DistortedEffectsPostprocess()
93
    {
94
    mID = ++mNextID;
95
    initializeEffectLists(this,0);
96
    }
97

  
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99
/**
100
 * Copy constructor.
101
 * <p>
102
 * Whatever we do not clone gets created just like in the default constructor.
103
 *
104
 * @param dc    Source object to create our object from
105
 * @param flags A bitmask of values specifying what to copy.
106
 *              Currently the only values possible are CLONE_NOTHING or CLONE_POSTPROCESS.
107
 */
108
  public DistortedEffectsPostprocess(DistortedEffectsPostprocess dc, int flags)
109
    {
110
    mID = ++mNextID;
111
    initializeEffectLists(dc,flags);
112
    }
113

  
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
/**
116
 * Releases all resources. After this call, the queue should not be used anymore.
117
 */
118
  @SuppressWarnings("unused")
119
  public synchronized void delete()
120
    {
121
    releasePriv();
122
    }
123

  
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
/**
126
 * Returns unique ID of this instance.
127
 *
128
 * @return ID of the object.
129
 */
130
  @SuppressWarnings("unused")
131
  public long getID()
132
      {
133
      return mID;
134
      }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
/**
138
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
139
 * to one of the Effects in the queues. Nothing will happen if 'el' is already in the list.
140
 * 
141
 * @param el A class implementing the EffectListener interface that wants to get notifications.
142
 */
143
  @SuppressWarnings("unused")
144
  public void registerForMessages(EffectListener el)
145
    {
146
    mP.registerForMessages(el);
147
    }
148

  
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
/**
151
 * Removes the calling class from the list of Listeners.
152
 * 
153
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
154
 */
155
  @SuppressWarnings("unused")
156
  public void deregisterForMessages(EffectListener el)
157
    {
158
    mP.deregisterForMessages(el);
159
    }
160

  
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
/**
163
 * Aborts all Effects.
164
 * @return Number of effects aborted.
165
 */
166
  @SuppressWarnings("unused")
167
  public int abortAllEffects()
168
      {
169
      return mP.abortAll(true);
170
      }
171

  
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
/**
174
 * Aborts all Effects of a given type (currently only POSTPROCESSING Effects).
175
 * 
176
 * @param type one of the constants defined in {@link EffectTypes}
177
 * @return Number of effects aborted.
178
 */
179
  @SuppressWarnings("unused")
180
  public int abortEffects(EffectTypes type)
181
    {
182
    switch(type)
183
      {
184
      case POSTPROCESS: return mP.abortAll(true);
185
      default         : return 0;
186
      }
187
    }
188
    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190
/**
191
 * Aborts a single Effect.
192
 * 
193
 * @param id ID of the Effect we want to abort.
194
 * @return number of Effects aborted. Always either 0 or 1.
195
 */
196
  @SuppressWarnings("unused")
197
  public int abortEffect(long id)
198
    {
199
    int type = (int)(id&EffectTypes.MASK);
200

  
201
    if( type==EffectTypes.POSTPROCESS.type ) return mP.removeByID(id>>EffectTypes.LENGTH);
202

  
203
    return 0;
204
    }
205

  
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207
/**
208
 * Abort all Effects of a given name, for example all blurs.
209
 * 
210
 * @param name one of the constants defined in {@link EffectNames}
211
 * @return number of Effects aborted.
212
 */
213
  @SuppressWarnings("unused")
214
  public int abortEffects(EffectNames name)
215
    {
216
    switch(name.getType())
217
      {
218
      case POSTPROCESS: return mP.removeByType(name);
219
      default         : return 0;
220
      }
221
    }
222
    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224
/**
225
 * Print some info about a given Effect to Android's standard out. Used for debugging only.
226
 * 
227
 * @param id Effect ID we want to print info about
228
 * @return <code>true</code> if a single Effect of type effectType has been found.
229
 */
230
  @SuppressWarnings("unused")
231
  public boolean printEffect(long id)
232
    {
233
    int type = (int)(id&EffectTypes.MASK);
234

  
235
    if( type==EffectTypes.POSTPROCESS.type )  return mP.printByID(id>>EffectTypes.LENGTH);
236

  
237
    return false;
238
    }
239

  
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
/**
242
 * Returns the maximum number of Postprocess effects.
243
 *
244
 * @return The maximum number of Postprocess effects
245
 */
246
  @SuppressWarnings("unused")
247
  public static int getMaxPostprocess()
248
    {
249
    return EffectQueue.getMax(EffectTypes.POSTPROCESS.ordinal());
250
    }
251

  
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253
/**
254
 * Sets the maximum number of Postprocess effects that can be stored in a single EffectQueue at one time.
255
 * This can fail if:
256
 * <ul>
257
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
258
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
259
 *     before the Fragment Shader gets compiled, i.e. before the call to {@link Distorted#onCreate}. After this
260
 *     time only decreasing the value of 'max' is permitted.
261
 * <li>Furthermore, this needs to be called before any instances of the DistortedEffects class get created.
262
 * </ul>
263
 *
264
 * @param max new maximum number of simultaneous Postprocess Effects. Has to be a non-negative number not greater
265
 *            than Byte.MAX_VALUE
266
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
267
 */
268
  @SuppressWarnings("unused")
269
  public static boolean setMaxPostprocess(int max)
270
    {
271
    return EffectQueue.setMax(EffectTypes.POSTPROCESS.ordinal(),max);
272
    }
273

  
274
///////////////////////////////////////////////////////////////////////////////////////////////////   
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
// Individual effect functions.
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278
// Postprocess-based effects
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280
/**
281
 * Blur the object.
282
 *
283
 * @param radius The 'strength' if the effect, in pixels. 0 = no blur, 10 = when blurring a given pixel,
284
 *               take into account 10 pixels in each direction.
285
 * @return ID of the effect added, or -1 if we failed to add one.
286
 */
287
  public long blur(Data1D radius)
288
    {
289
    return mP.add(EffectNames.BLUR, radius);
290
    }
291
  }
src/main/java/org/distorted/library/DistortedNode.java
43 43
  private DistortedNode mParent;
44 44
  private MeshObject mMesh;
45 45
  private DistortedEffects mEffects;
46
  private DistortedEffectsPostprocess mPostprocess;
46 47
  private DistortedInputSurface mSurface;
47 48
  private DistortedRenderState mState;
48 49
  private NodeData mData;
......
211 212
    return 0;
212 213
    }
213 214

  
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

  
216
  int postprocess(long currTime, DistortedOutputSurface surface)
217
    {
218
    return mEffects.postprocessPriv(currTime,surface);
219
    }
220

  
221 215
///////////////////////////////////////////////////////////////////////////////////////////////////
222 216

  
223 217
  EffectQueuePostprocess getPostprocess()
224 218
    {
225
    return mEffects.getPostprocess();
219
    return mPostprocess==null ? null : mPostprocess.getPostprocess();
226 220
    }
227 221

  
228 222
///////////////////////////////////////////////////////////////////////////////////////////////////
......
269 263
    {
270 264
    mSurface       = surface;
271 265
    mEffects       = effects;
266
    mPostprocess   = null;
272 267
    mMesh          = mesh;
273 268
    mState         = new DistortedRenderState();
274 269
    mChildren      = null;
......
305 300
 */
306 301
  public DistortedNode(DistortedNode node, int flags)
307 302
    {
308
    mEffects= new DistortedEffects(node.mEffects,flags);
309
    mMesh   = node.mMesh;
310
    mState  = new DistortedRenderState();
311
    mParent = null;
303
    mEffects     = new DistortedEffects(node.mEffects,flags);
304
    mPostprocess = null;
305
    mMesh        = node.mMesh;
306
    mState       = new DistortedRenderState();
307
    mParent      = null;
312 308

  
313 309
    if( (flags & Distorted.CLONE_SURFACE) != 0 )
314 310
      {
......
521 517
      }
522 518
    }
523 519

  
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521
/**
522
 * Sets the Postprocessing Effects we will apply to the temporary buffer this Node - and fellow siblings
523
 * with the same Effects - will get rendered to.
524
 * <p>
525
 * For efficiency reasons, it is very important to assign the very same DistortedEffectsPostprocess
526
 * object to all the DistortedNode siblings that are supposed to be postprocessed in the same way,
527
 * because only then will the library assign all such siblings to the same 'Bucket' which gets rendered
528
 * to the same offscreen buffer which then gets postprocessed in one go and subsequently merged to the
529
 * target Surface.
530
 */
531
  public void setPostprocessEffects(DistortedEffectsPostprocess dep)
532
    {
533
    mPostprocess = dep;
534

  
535
    // TODO: rearrange all the siblings so that all are sorted by the DistortedEffectsPostprocess' ID.
536
    }
537

  
524 538
///////////////////////////////////////////////////////////////////////////////////////////////////
525 539
/**
526 540
 * Returns the DistortedEffects object that's in the Node.
......
564 578
 * @param b Write to the BLUE color channel when rendering this Node?
565 579
 * @param a Write to the ALPHA channel when rendering this Node?
566 580
 */
581
  @SuppressWarnings("unused")
567 582
  public void glColorMask(boolean r, boolean g, boolean b, boolean a)
568 583
    {
569 584
    mState.glColorMask(r,g,b,a);
......
575 590
 *
576 591
 * @param mask Write to the Depth buffer when rendering this Node?
577 592
 */
593
  @SuppressWarnings("unused")
578 594
  public void glDepthMask(boolean mask)
579 595
    {
580 596
    mState.glDepthMask(mask);
......
586 602
 *
587 603
 * @param mask Marks the bits of the Stencil buffer we will write to when rendering this Node.
588 604
 */
605
  @SuppressWarnings("unused")
589 606
  public void glStencilMask(int mask)
590 607
    {
591 608
    mState.glStencilMask(mask);
......
597 614
 *
598 615
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
599 616
 */
617
  @SuppressWarnings("unused")
600 618
  public void glEnable(int test)
601 619
    {
602 620
    mState.glEnable(test);
......
608 626
 *
609 627
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
610 628
 */
629
  @SuppressWarnings("unused")
611 630
  public void glDisable(int test)
612 631
    {
613 632
    mState.glDisable(test);
......
621 640
 * @param ref  Reference valut to compare our stencil with.
622 641
 * @param mask Mask used when comparing.
623 642
 */
643
  @SuppressWarnings("unused")
624 644
  public void glStencilFunc(int func, int ref, int mask)
625 645
    {
626 646
    mState.glStencilFunc(func,ref,mask);
......
636 656
 * @param dpfail What to do when Depth Test fails.
637 657
 * @param dppass What to do when Depth Test passes.
638 658
 */
659
  @SuppressWarnings("unused")
639 660
  public void glStencilOp(int sfail, int dpfail, int dppass)
640 661
    {
641 662
    mState.glStencilOp(sfail,dpfail,dppass);
......
647 668
 *
648 669
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
649 670
 */
671
  @SuppressWarnings("unused")
650 672
  public void glDepthFunc(int func)
651 673
    {
652 674
    mState.glDepthFunc(func);
......
663 685
 * @param src Source Blend function
664 686
 * @param dst Destination Blend function
665 687
 */
688
  @SuppressWarnings("unused")
666 689
  public void glBlendFunc(int src, int dst)
667 690
    {
668 691
    mState.glBlendFunc(src,dst);
src/main/java/org/distorted/library/DistortedOutputSurface.java
133 133
      {
134 134
      child = children.get(i);
135 135
      currP = child.getPostprocess();
136
      currB = currP.getBucket();
136
      currB = currP==null ? 0 : currP.getBucket();
137 137

  
138
      if( i>0 && currB!=lastB ) numRenders += lastP.postprocess(time,this);
138
      if( lastB!=currB && lastB!=0 )
139
        {
140
        //android.util.Log.e("output", "i="+i+" postprocess and merge");
141
        numRenders += lastP.postprocess(time,this);
142
        }
139 143

  
140
      if( currB==0 ) numRenders += child.draw(time,this);
144
      if( currB==0 )
145
        {
146
        //android.util.Log.e("output", "i="+i+" draw to this");
147
        numRenders += child.draw(time,this);
148
        }
141 149
      else
142 150
        {
143 151
        if( mBuffer1==null )
......
146 154
          mBuffer2 = new DistortedFramebuffer(false                     , DistortedSurface.TYPE_TREE, mWidth, mHeight);
147 155
          }
148 156

  
157
        //android.util.Log.e("output", "i="+i+" draw to buffer");
149 158
        numRenders += child.draw(time,mBuffer1);
150
        if( i==num-1 ) numRenders += currP.postprocess(time,this);
159
        if( i==num-1 )
160
          {
161
          //android.util.Log.e("output", "i="+i+" postprocess and merge");
162
          numRenders += currP.postprocess(time,this);
163
          }
151 164
        }
152 165

  
153 166
      lastP = currP;

Also available in: Unified diff