Project

General

Profile

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

library / src / main / java / org / distorted / library / main / DistortedNode.java @ 835b197e

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.opengl.GLES30;
23

    
24
import org.distorted.library.mesh.MeshBase;
25

    
26
import java.util.ArrayList;
27
import java.util.Collections;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30
/**
31
 * Class which represents a Node in a Tree of (InputSurface,Mesh,Effects) triplets.
32
 * <p>
33
 * Having organized such sets into a Tree, we can then render any Node to any OutputSurface.
34
 * That recursively renders the set held in the Node and all its children.
35
 * <p>
36
 * The class takes special care to only render identical sub-trees once. Each Node holds a reference
37
 * to sub-class 'NodeData'. Two identical sub-trees attached at different points of the main tree
38
 * will point to the same NodeData; only the first of this is rendered (mData.numRender!).
39
 */
40
public class DistortedNode implements InternalChildrenList.Parent
41
  {
42
  private static final int DEFAULT_FBO_SIZE = 100;
43

    
44
  private MeshBase mMesh;
45
  private DistortedEffects mEffects;
46
  private InternalSurface mSurface;
47
  private InternalRenderState mState;
48
  private InternalNodeData mData;
49
  private InternalChildrenList mChildren;
50
  private InternalChildrenList.Parent mParent;
51

    
52
  private int mFboW, mFboH, mFboDepthStencil;
53
  private boolean mRenderWayOIT;
54
  private float mFOV, mNear;
55
  private long mLastTime;
56

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

    
59
  public void markForDeletion()
60
    {
61
    if( mData.removeData() )
62
      {
63
      mData.mFBO.markForDeletion();
64
      mData.mFBO = null;
65
      }
66
    }
67

    
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69
// [3] --> the postprocessing queue. See EffectType.
70

    
71
  long getBucket()
72
    {
73
    return mEffects.getQueues()[3].getID();
74
    }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  private ArrayList<Long> generateIDList()
79
    {
80
    ArrayList<Long> ret = new ArrayList<>();
81
    int numChildren = mChildren.getNumChildren();
82

    
83
    if( numChildren==0 )
84
      {
85
      // add a negative number so this leaf never gets confused with a internal node
86
      // with a single child that happens to have ID identical to some leaf's Effects ID.
87
      ret.add(-mEffects.getID());
88
      }
89
    else
90
      {
91
      DistortedNode node;
92
   
93
      for(int i=0; i<numChildren; i++)
94
        {
95
        node = mChildren.getChild(i);
96
        ret.add(node.mData.ID);
97
        }
98

    
99
      // A bit questionable decision here - we are sorting the children IDs, which means
100
      // that order in which we draw the children is going to be undefined (well, this is not
101
      // strictly speaking true - when rendering, if no postprocessing and isomorphism are
102
      // involved, we *DO* render the children in order they were added; if however there
103
      // are two internal nodes with the same list of identical children, just added in a
104
      // different order each time, then we consider them isomorphic, i.e. identical and only
105
      // render the first one. If then two children of such 'pseudo-isomorphic' nodes are at
106
      // exactly the same Z-height this might result in some unexpected sights).
107
      //
108
      // Reason: with the children being sorted by postprocessing buckets, the order is
109
      // undefined anyway (although only when postprocessing is applied).
110
      //
111
      // See the consequences in the 'Olympic' app - remove a few leaves and add them back in
112
      // different order. You will see the number of renders go back to the original 15.
113
      Collections.sort(ret);
114
      }
115

    
116
    ret.add( 0, mSurface.getID() );
117

    
118
    return ret;
119
    }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
/**
123
 * This is not really part of the public API. Has to be public only because it is a part of the
124
 * InternalChildrenList.Parent interface.
125
 *
126
 * @y.exclude
127
 */
128
  public void adjustIsomorphism()
129
    {
130
    InternalNodeData newData = InternalNodeData.returnData(generateIDList());
131
    boolean deleteOldFBO = mData.removeData();
132
    boolean createNewFBO = (mChildren.getNumChildren()>0 && newData.mFBO==null);
133

    
134
    if( deleteOldFBO && createNewFBO )
135
      {
136
      newData.mFBO = mData.mFBO;
137
      }
138
    else if( deleteOldFBO )
139
      {
140
      mData.mFBO.markForDeletion();
141
      mData.mFBO = null;
142
      }
143
    else if( createNewFBO )
144
      {
145
      newData.mFBO = allocateNewFBO();
146
      }
147

    
148
    mData = newData;
149

    
150
    if( mParent!=null ) mParent.adjustIsomorphism();
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154
// return the total number of render calls issued
155

    
156
  int drawNoBlend(long currTime, InternalOutputSurface surface)
157
    {
158
    InternalSurface input = getSurface();
159

    
160
    if( input.setAsInput() )
161
      {
162
      mState.apply();
163
      GLES30.glDisable(GLES30.GL_BLEND);
164
      if( mLastTime==0 ) mLastTime=currTime;
165
      DistortedLibrary.drawPriv(mEffects, mMesh, surface, currTime, (currTime-mLastTime));
166
      mLastTime = currTime;
167
      GLES30.glEnable(GLES30.GL_BLEND);
168
      return 1;
169
      }
170

    
171
    return 0;
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175
// Use the Order Independent Transparency method to draw a non-postprocessed child.
176

    
177
  int drawOIT(long currTime, InternalOutputSurface surface)
178
    {
179
    InternalSurface input = getSurface();
180

    
181
    if( input.setAsInput() )
182
      {
183
      mState.apply();
184
      if( mLastTime==0 ) mLastTime=currTime;
185
      DistortedLibrary.drawPrivOIT(mEffects, mMesh, surface, currTime, (currTime-mLastTime));
186
      mLastTime = currTime;
187
      return 1;
188
      }
189

    
190
    return 0;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
// return the total number of render calls issued
195

    
196
  int draw(long currTime, InternalOutputSurface surface)
197
    {
198
    InternalSurface input = getSurface();
199

    
200
    if( input.setAsInput() )
201
      {
202
      mState.apply();
203
      if( mLastTime==0 ) mLastTime=currTime;
204
      DistortedLibrary.drawPriv(mEffects, mMesh, surface, currTime, (currTime-mLastTime));
205
      mLastTime = currTime;
206
      return 1;
207
      }
208

    
209
    return 0;
210
    }
211

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
// return the total number of render calls issued
214

    
215
  int renderRecursive(long currTime)
216
    {
217
    int numRenders = 0;
218
    int numChildren = mChildren.getNumChildren();
219

    
220
    if( numChildren>0 && mData.notRenderedYetAtThisTime(currTime) )
221
      {
222
      DistortedNode node;
223
      long oldBucket=0, newBucket;
224

    
225
      for (int i=0; i<numChildren; i++)
226
        {
227
        node = mChildren.getChild(i);
228
        newBucket = node.getBucket();
229
        numRenders += node.renderRecursive(currTime);
230
        if( newBucket<oldBucket ) mChildren.rearrangeByBuckets(i,newBucket);
231
        else oldBucket=newBucket;
232
        }
233

    
234
      if( mData.mFBO==null ) mData.mFBO = allocateNewFBO();
235
      mData.mFBO.setAsOutput(currTime);
236

    
237
      if( mSurface.setAsInput() )
238
        {
239
        numRenders++;
240
        DistortedLibrary.blitPriv(mData.mFBO);
241
        }
242

    
243
      numRenders += mData.mFBO.renderChildren(currTime,numChildren,mChildren,0, mRenderWayOIT);
244
      }
245

    
246
    return numRenders;
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  private DistortedFramebuffer allocateNewFBO()
252
    {
253
    int width, height;
254

    
255
    if( mFboW>0 && mFboH>0 )
256
      {
257
      width = mFboW;
258
      height= mFboH;
259
      }
260
    else
261
      {
262
      if( mSurface instanceof DistortedFramebuffer )
263
        {
264
        DistortedFramebuffer fbo = (DistortedFramebuffer)mSurface;
265
        width = fbo.mWidth;
266
        height= fbo.mHeight;
267
        }
268
      else
269
        {
270
        width = DEFAULT_FBO_SIZE;
271
        height= DEFAULT_FBO_SIZE;
272
        }
273
      }
274

    
275
    DistortedFramebuffer fbo = new DistortedFramebuffer(1,mFboDepthStencil, InternalSurface.TYPE_TREE, width, height);
276

    
277
    if( mFOV!=InternalOutputSurface.DEFAULT_FOV || mNear!=InternalOutputSurface.DEFAULT_NEAR )
278
      {
279
      fbo.setProjection(mFOV,mNear);
280
      }
281

    
282
    return fbo;
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  void setParent(InternalChildrenList.Parent parent)
288
    {
289
    mParent = parent;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293
// PUBLIC API
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295
/**
296
 * Constructs new Node.
297
 *     
298
 * @param surface InputSurface to put into the new Node.
299
 * @param effects DistortedEffects to put into the new Node.
300
 * @param mesh MeshBase to put into the new Node.
301
 */
302
  public DistortedNode(InternalSurface surface, DistortedEffects effects, MeshBase mesh)
303
    {
304
    mLastTime      = 0;
305
    mSurface       = surface;
306
    mEffects       = effects;
307
    mMesh          = mesh;
308
    mState         = new InternalRenderState();
309
    mChildren      = new InternalChildrenList(this);
310
    mParent        = null;
311
    mRenderWayOIT  = false;
312

    
313
    mFOV = InternalOutputSurface.DEFAULT_FOV;
314
    mNear= InternalOutputSurface.DEFAULT_NEAR;
315

    
316
    mFboW            = 0;  // i.e. take this from
317
    mFboH            = 0;  // mEffects's stretch{X,Y}
318
    mFboDepthStencil = DistortedFramebuffer.DEPTH_NO_STENCIL;
319

    
320
    mData = InternalNodeData.returnData(generateIDList());
321
    }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////  
324
/**
325
 * Copy-constructs new Node from another Node.
326
 *     
327
 * @param node The DistortedNode to copy data from.
328
 * @param flags bit field composed of a subset of the following:
329
 *        {@link DistortedLibrary#CLONE_SURFACE},  {@link DistortedLibrary#CLONE_MATRIX}, {@link DistortedLibrary#CLONE_VERTEX},
330
 *        {@link DistortedLibrary#CLONE_FRAGMENT} and {@link DistortedLibrary#CLONE_CHILDREN}.
331
 *        For example flags = CLONE_SURFACE | CLONE_CHILDREN.
332
 */
333
  public DistortedNode(DistortedNode node, int flags)
334
    {
335
    mLastTime     = 0;
336
    mEffects      = new DistortedEffects(node.mEffects,flags);
337
    mMesh         = node.mMesh;
338
    mState        = new InternalRenderState();
339
    mParent       = null;
340
    mRenderWayOIT = false;
341

    
342
    mFOV = InternalOutputSurface.DEFAULT_FOV;
343
    mNear= InternalOutputSurface.DEFAULT_NEAR;
344

    
345
    mFboW            = node.mFboW;
346
    mFboH            = node.mFboH;
347
    mFboDepthStencil = node.mFboDepthStencil;
348

    
349
    if( (flags & DistortedLibrary.CLONE_SURFACE) != 0 )
350
      {
351
      mSurface = node.mSurface;
352
      }
353
    else
354
      {
355
      if( node.mSurface instanceof DistortedTexture )
356
        {
357
        mSurface = new DistortedTexture(InternalSurface.TYPE_TREE);
358
        }
359
      else if( node.mSurface instanceof DistortedFramebuffer )
360
        {
361
        DistortedFramebuffer fbo = (DistortedFramebuffer)node.mSurface;
362

    
363
        int w = fbo.getWidth();
364
        int h = fbo.getHeight();
365
        int depthStencil = DistortedFramebuffer.NO_DEPTH_NO_STENCIL;
366

    
367
        if( fbo.hasDepth() )
368
          {
369
          boolean hasStencil = fbo.hasStencil();
370
          depthStencil = (hasStencil ? DistortedFramebuffer.BOTH_DEPTH_STENCIL:DistortedFramebuffer.DEPTH_NO_STENCIL);
371
          }
372

    
373
        mSurface = new DistortedFramebuffer(1,depthStencil, InternalSurface.TYPE_TREE,w,h);
374
        }
375
      }
376

    
377
    if( (flags & DistortedLibrary.CLONE_CHILDREN) != 0 )
378
      {
379
      mChildren = node.mChildren;
380
      }
381
    else
382
      {
383
      mChildren = new InternalChildrenList(this);
384
      }
385

    
386
    mData = InternalNodeData.returnData(generateIDList());
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390
  /**
391
   * When rendering this Node, should we use the Order Independent Transparency render more?
392
   * <p>
393
   * There are two modes of rendering: the fast 'normal' way, which however renders transparent
394
   * fragments in different ways depending on which fragments get rendered first, or the slower
395
   * 'oit' way, which renders transparent fragments correctly regardless of their order.
396
   *
397
   * @param oit True if we want to render more slowly, but in a way which accounts for transparency.
398
   */
399
  public void setOrderIndependentTransparency(boolean oit)
400
    {
401
    mRenderWayOIT = oit;
402
    }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405
  /**
406
   * When rendering this Node, should we use the Order Independent Transparency render more?
407
   * <p>
408
   * There are two modes of rendering: the fast 'normal' way, which however renders transparent
409
   * fragments in different ways depending on which fragments get rendered first, or the slower
410
   * 'oit' way, which renders transparent fragments correctly regardless of their order.
411
   *
412
   * @param oit True if we want to render more slowly, but in a way which accounts for transparency.
413
   * @param initialSize Initial number of transparent fragments we expect, in screenfulls.
414
   *                    I.e '1.0' means 'the scene we are going to render contains dialog_about 1 screen
415
   *                    worth of transparent fragments'. Valid values: 0.0 &lt; initialSize &lt; 10.0
416
   *                    Even if you get this wrong, the library will detect that there are more
417
   *                    transparent fragments than it has space for and readjust its internal buffers,
418
   *                    but only after a few frames during which one will probably see missing objects.
419
   */
420
  public void setOrderIndependentTransparency(boolean oit, float initialSize)
421
    {
422
    mRenderWayOIT = oit;
423

    
424
    if( initialSize>0.0f && initialSize<10.0f )
425
      DistortedLibrary.setSSBOSize(initialSize);
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429
/**
430
 * Adds a new child to the last position in the list of our Node's children.
431
 * <p>
432
 * We cannot do this mid-render - actual attachment will be done just before the next render, by the
433
 * InternalMaster (by calling doWork())
434
 *
435
 * @param node The new Node to add.
436
 */
437
  public void attach(DistortedNode node)
438
    {
439
    mChildren.attach(node);
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
/**
444
 * Adds a new child to the last position in the list of our Node's children.
445
 * <p>
446
 * We cannot do this mid-render - actual attachment will be done just before the next render, by the
447
 * InternalMaster (by calling doWork())
448
 *
449
 * @param surface InputSurface to initialize our child Node with.
450
 * @param effects DistortedEffects to initialize our child Node with.
451
 * @param mesh MeshBase to initialize our child Node with.
452
 * @return the newly constructed child Node, or null if we couldn't allocate resources.
453
 */
454
  public DistortedNode attach(InternalSurface surface, DistortedEffects effects, MeshBase mesh)
455
    {
456
    return mChildren.attach(surface,effects,mesh);
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
/**
461
 * Removes the first occurrence of a specified child from the list of children of our Node.
462
 * <p>
463
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
464
 * InternalMaster (by calling doWork())
465
 *
466
 * @param node The Node to remove.
467
 */
468
  public void detach(DistortedNode node)
469
    {
470
    mChildren.detach(node);
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474
/**
475
 * Removes the first occurrence of a specified child from the list of children of our Node.
476
 * <p>
477
 * A bit questionable method as there can be many different Nodes attached as children, some
478
 * of them having the same Effects but - for instance - different Mesh. Use with care.
479
 * <p>
480
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
481
 * InternalMaster (by calling doWork())
482
 *
483
 * @param effects DistortedEffects to remove.
484
 */
485
  public void detach(DistortedEffects effects)
486
    {
487
    mChildren.detach(effects);
488
    }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491
/**
492
 * Removes all children Nodes.
493
 * <p>
494
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
495
 * InternalMaster (by calling doWork())
496
 */
497
  public void detachAll()
498
    {
499
    mChildren.detachAll();
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503
/**
504
 * Returns the DistortedEffects object that's in the Node.
505
 * 
506
 * @return The DistortedEffects contained in the Node.
507
 */
508
  public DistortedEffects getEffects()
509
    {
510
    return mEffects;
511
    }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514
  /**
515
   * Returns the surface this object gets rendered to.
516
   *
517
   * @return The InternalSurface contained in the Node (if a leaf), or the FBO (if an internal Node)
518
   */
519
  public InternalSurface getSurface()
520
    {
521
    return mChildren.getNumChildren()==0 ? mSurface : mData.mFBO;
522
    }
523

    
524
///////////////////////////////////////////////////////////////////////////////////////////////////
525
/**
526
 * Returns the Mesh object that's in the Node.
527
 *
528
 * @return Mesh contained in the Node.
529
 */
530
  public MeshBase getMesh()
531
    {
532
    return mMesh;
533
    }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536
/**
537
 * Resizes the DistortedFramebuffer object that we render this Node to.
538
 */
539
  public void resizeFBO(int width, int height)
540
    {
541
    mFboW = width;
542
    mFboH = height;
543

    
544
    if ( mData.mFBO !=null )
545
      {
546
      // TODO: potentially allocate a new NodeData if we have to
547
      mData.mFBO.resize(width,height);
548
      }
549
    }
550

    
551
///////////////////////////////////////////////////////////////////////////////////////////////////
552
/**
553
 * Set Projection Matrix for the Framebuffer contained in this Node.
554
 * <p>
555
 * If this Node is a Leaf and has no Framebuffer in it, this call does nothing.
556
 *
557
 * @param fov Vertical 'field of view' of the Projection frustrum (in degrees).
558
 *            Valid values: 0<=fov<180. FOV==0 means 'parallel projection'.
559
 * @param near The Near plane.
560
 */
561
  public void setProjection(float fov, float near)
562
    {
563
    if( fov < 180.0f && fov >=0.0f )
564
      {
565
      mFOV = fov;
566
      }
567

    
568
    if( near<   1.0f && near> 0.0f )
569
      {
570
      mNear= near;
571
      }
572
    else if( near<=0.0f )
573
      {
574
      mNear = 0.01f;
575
      }
576
    else if( near>=1.0f )
577
      {
578
      mNear=0.99f;
579
      }
580

    
581
    if( mData.mFBO!=null )
582
      {
583
      mData.mFBO.setProjection(mFOV,mNear);
584
      }
585
    }
586

    
587
///////////////////////////////////////////////////////////////////////////////////////////////////
588
/**
589
 * Enables/disables DEPTH and STENCIL buffers in the Framebuffer object that we render this Node to.
590
 */
591
  public void enableDepthStencil(int depthStencil)
592
    {
593
    mFboDepthStencil = depthStencil;
594

    
595
    if ( mData.mFBO !=null )
596
      {
597
      // TODO: potentially allocate a new NodeData if we have to
598
      mData.mFBO.enableDepthStencil(depthStencil);
599
      }
600
    }
601

    
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603
// APIs that control how to set the OpenGL state just before rendering this Node.
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605
/**
606
 * When rendering this Node, use ColorMask (r,g,b,a).
607
 *
608
 * @param r Write to the RED color channel when rendering this Node?
609
 * @param g Write to the GREEN color channel when rendering this Node?
610
 * @param b Write to the BLUE color channel when rendering this Node?
611
 * @param a Write to the ALPHA channel when rendering this Node?
612
 */
613
  @SuppressWarnings("unused")
614
  public void glColorMask(boolean r, boolean g, boolean b, boolean a)
615
    {
616
    mState.glColorMask(r,g,b,a);
617
    }
618

    
619
///////////////////////////////////////////////////////////////////////////////////////////////////
620
/**
621
 * When rendering this Node, switch on writing to Depth buffer?
622
 *
623
 * @param mask Write to the Depth buffer when rendering this Node?
624
 */
625
  @SuppressWarnings("unused")
626
  public void glDepthMask(boolean mask)
627
    {
628
    mState.glDepthMask(mask);
629
    }
630

    
631
///////////////////////////////////////////////////////////////////////////////////////////////////
632
/**
633
 * When rendering this Node, which bits of the Stencil buffer to write to?
634
 *
635
 * @param mask Marks the bits of the Stencil buffer we will write to when rendering this Node.
636
 */
637
  @SuppressWarnings("unused")
638
  public void glStencilMask(int mask)
639
    {
640
    mState.glStencilMask(mask);
641
    }
642

    
643
///////////////////////////////////////////////////////////////////////////////////////////////////
644
/**
645
 * When rendering this Node, which Tests to enable?
646
 *
647
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
648
 */
649
  @SuppressWarnings("unused")
650
  public void glEnable(int test)
651
    {
652
    mState.glEnable(test);
653
    }
654

    
655
///////////////////////////////////////////////////////////////////////////////////////////////////
656
/**
657
 * When rendering this Node, which Tests to enable?
658
 *
659
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
660
 */
661
  @SuppressWarnings("unused")
662
  public void glDisable(int test)
663
    {
664
    mState.glDisable(test);
665
    }
666

    
667
///////////////////////////////////////////////////////////////////////////////////////////////////
668
/**
669
 * When rendering this Node, use the following StencilFunc.
670
 *
671
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
672
 * @param ref  Reference valut to compare our stencil with.
673
 * @param mask Mask used when comparing.
674
 */
675
  @SuppressWarnings("unused")
676
  public void glStencilFunc(int func, int ref, int mask)
677
    {
678
    mState.glStencilFunc(func,ref,mask);
679
    }
680

    
681
///////////////////////////////////////////////////////////////////////////////////////////////////
682
/**
683
 * When rendering this Node, use the following StencilOp.
684
 * <p>
685
 * Valid values of all 3 parameters: GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP
686
 *
687
 * @param sfail  What to do when Stencil Test fails.
688
 * @param dpfail What to do when Depth Test fails.
689
 * @param dppass What to do when Depth Test passes.
690
 */
691
  @SuppressWarnings("unused")
692
  public void glStencilOp(int sfail, int dpfail, int dppass)
693
    {
694
    mState.glStencilOp(sfail,dpfail,dppass);
695
    }
696

    
697
///////////////////////////////////////////////////////////////////////////////////////////////////
698
/**
699
 * When rendering this Node, use the following DepthFunc.
700
 *
701
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
702
 */
703
  @SuppressWarnings("unused")
704
  public void glDepthFunc(int func)
705
    {
706
    mState.glDepthFunc(func);
707
    }
708

    
709
///////////////////////////////////////////////////////////////////////////////////////////////////
710
/**
711
 * When rendering this Node, use the following Blending mode.
712
 * <p>
713
 * Valid values: GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
714
 *               GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
715
 *               GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE
716
 *
717
 * @param src Source Blend function
718
 * @param dst Destination Blend function
719
 */
720
  @SuppressWarnings("unused")
721
  public void glBlendFunc(int src, int dst)
722
    {
723
    mState.glBlendFunc(src,dst);
724
    }
725

    
726
///////////////////////////////////////////////////////////////////////////////////////////////////
727
/**
728
 * Before rendering this Node, clear the following buffers.
729
 * <p>
730
 * Valid values: 0, or bitwise OR of one or more values from the set GL_COLOR_BUFFER_BIT,
731
 *               GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT.
732
 * Default: 0
733
 *
734
 * @param mask bitwise OR of BUFFER_BITs to clear.
735
 */
736
  @SuppressWarnings("unused")
737
  public void glClear(int mask)
738
    {
739
    mState.glClear(mask);
740
    }
741
  }
(4-4/16)