Project

General

Profile

« Previous | Next » 

Revision 178983f4

Added by Leszek Koltunski over 1 year ago

Remove the requirement that not-postprocessed children in the render scene must be in the first bucket.
Seriously simplify renderChildren().

View differences:

src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
165 165

  
166 166
  public boolean getRenderDirectly()
167 167
    {
168
    return mNumEffects > 0 && ((PostprocessEffect) mEffects[0]).getRenderDirectly();
168
    return mNumEffects>0 && ((PostprocessEffect) mEffects[0]).getRenderDirectly();
169 169
    }
170 170

  
171 171
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/main/InternalChildrenList.java
99 99
// Can make this logarithmic but the typical number of children is very small anyway.
100 100
//
101 101
// We want to keep same buckets next to each other, while avoiding changes in order of the children
102
// (if possible!) We want to keep bucket=0 (i.e. the non-postprocessed children) at the beginning.
102
// (if possible!)
103
// 2022/10/25: removed keeping bucket 0 (i.e. non-postprocessed children) always in the front -
104
// we don't need it (given the fixes to renderChildren() )
103 105

  
104 106
  private void addSortingByBuckets(DistortedNode newChild)
105 107
    {
106 108
    int i;
107 109
    long bucket = newChild.getBucket();
108
    boolean sameBucket = false;
110
    boolean thisSame,lastSame = false;
109 111

  
110 112
    for(i=0; i<mNumChildren; i++)
111 113
      {
112
      if( mChildren.get(i).getBucket() == bucket )
113
        {
114
        sameBucket=true;
115
        }
116
      else if( sameBucket || bucket==0 )
117
        {
118
        break;
119
        }
114
      thisSame= (mChildren.get(i).getBucket()==bucket);
115
      if( lastSame && !thisSame ) break;
116
      lastSame = thisSame;
120 117
      }
121 118

  
122 119
    mChildren.add(i,newChild);
src/main/java/org/distorted/library/main/InternalOutputSurface.java
54 54

  
55 55
  // Global buffers used for postprocessing
56 56
  private final static DistortedFramebuffer[] mBuffer= new DistortedFramebuffer[EffectQuality.LENGTH];
57
  private final boolean[] mBufferInitialized;
57 58

  
58 59
  float mDistance, mNear, mMipmap;
59 60
  float[] mProjectionMatrix;
......
105 106
                          // round of create(), but before we start rendering.
106 107
                          // Create an empty FBO and Time here so that setAsOutput() is always safe to call.
107 108

  
109
    mBufferInitialized = new boolean[EffectQuality.LENGTH];
110

  
108 111
    allocateStuffDependantOnNumFBOS();
109 112
    createProjection();
110 113
    }
......
218 221
        }
219 222
    }
220 223

  
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222
// The postprocessing buffers mBuffer[] are generally speaking too large (there's just one static
223
// set of them) so before we use them for output, we need to adjust the Viewport as if they were
224
// smaller. That takes care of outputting pixels to them. When we use them as input, we have to
225
// adjust the texture coords - see the get{Width|Height}Correction functions.
226
//
227
// Also, adjust the Buffers so their Projection is the same like the surface we are supposed to be
228
// rendering to.
229

  
230
  private static void clonePostprocessingViewportAndProjection(InternalOutputSurface surface, InternalOutputSurface from)
231
    {
232
    if( surface.mWidth != from.mWidth || surface.mHeight != from.mHeight ||
233
        surface.mFOV   != from.mFOV   || surface.mNear   != from.mNear    )
234
      {
235
      surface.mWidth  = (int)(from.mWidth *surface.mMipmap);
236
      surface.mHeight = (int)(from.mHeight*surface.mMipmap);
237
      surface.mFOV    = from.mFOV;
238
      surface.mNear   = from.mNear;  // Near plane is independent of the mipmap level
239

  
240
      surface.createProjection();
241

  
242
      int maxw = Math.max(surface.mWidth , surface.mRealWidth );
243
      int maxh = Math.max(surface.mHeight, surface.mRealHeight);
244

  
245
      if (maxw > surface.mRealWidth || maxh > surface.mRealHeight)
246
        {
247
        surface.mRealWidth = maxw;
248
        surface.mRealHeight = maxh;
249

  
250
        surface.recreate();
251
        surface.create();
252
        }
253
      }
254
    }
255

  
256 224
///////////////////////////////////////////////////////////////////////////////////////////////////
257 225

  
258 226
  private int blitWithDepth(long currTime, InternalOutputSurface buffer, int fbo)
......
373 341
    mCurrFBO = fbo;
374 342
    }
375 343

  
344
///////////////////////////////////////////////////////////////////////////////////////////////////
345
// Render all children from the current bucket to the buffer, apply the postprocessing once to the
346
// whole buffer (queue.postprocess) and merge it to 'this' (oitBuild or blitWithDepth depending on
347
// the type of rendering)
348

  
349
  private int accumulateAndBlit(EffectQueuePostprocess queue, InternalChildrenList children, DistortedFramebuffer buffer,
350
                                int begIndex, int endIndex, boolean isFinal, long time, int fbo, boolean oit )
351
    {
352
    int numRenders = 0;
353

  
354
    for(int j=begIndex; j<endIndex; j++)
355
       {
356
       DistortedNode node = children.getChild(j);
357

  
358
       if( node.getSurface().setAsInput() )
359
         {
360
         buffer.setAsOutput();
361
         numRenders += queue.preprocess( buffer, node, buffer.mDistance, buffer.mMipmap, buffer.mProjectionMatrix );
362
         }
363
       }
364
    numRenders += queue.postprocess(buffer);
365

  
366
    if( oit )
367
      {
368
      numRenders += oitBuild(time, buffer, fbo);
369
      GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
370
      buffer.clearBuffer(fbo);
371
      }
372
    else
373
      {
374
      numRenders += blitWithDepth(time, buffer, fbo);
375
      if( !isFinal ) buffer.clearBuffer(fbo);
376
      }
377

  
378
    return numRenders;
379
    }
380

  
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

  
383
  private int renderChildToThisOrToBuffer(DistortedNode child, DistortedFramebuffer buffer, long time, boolean oit, boolean toThis)
384
    {
385
    int numRenders;
386

  
387
    if( toThis )
388
      {
389
      setAsOutput(time);
390

  
391
      if( oit )
392
        {
393
        numRenders = child.drawOIT(time, this);
394
        GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
395
        }
396
      else
397
        {
398
        numRenders = child.draw(time, this);
399
        }
400
      }
401
    else
402
      {
403
      buffer.setAsOutput(time);
404
      numRenders = child.drawNoBlend(time, buffer);
405
      }
406

  
407
    return numRenders;
408
    }
409

  
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411
// The postprocessing buffers mBuffer[] are generally speaking too large (there's just one static
412
// set of them) so before we use them for output, we need to adjust the Viewport as if they were
413
// smaller. That takes care of outputting pixels to them. When we use them as input, we have to
414
// adjust the texture coords - see the get{Width|Height}Correction functions.
415
//
416
// Also, adjust the Buffers so their Projection is the same like the surface we are supposed to be
417
// rendering to.
418

  
419
  private void clonePostprocessingViewportAndProjection(InternalOutputSurface surface, InternalOutputSurface from)
420
    {
421
    if( surface.mWidth != from.mWidth || surface.mHeight != from.mHeight ||
422
        surface.mFOV   != from.mFOV   || surface.mNear   != from.mNear    )
423
      {
424
      surface.mWidth  = (int)(from.mWidth *surface.mMipmap);
425
      surface.mHeight = (int)(from.mHeight*surface.mMipmap);
426
      surface.mFOV    = from.mFOV;
427
      surface.mNear   = from.mNear;  // Near plane is independent of the mipmap level
428

  
429
      surface.createProjection();
430

  
431
      int maxw = Math.max(surface.mWidth , surface.mRealWidth );
432
      int maxh = Math.max(surface.mHeight, surface.mRealHeight);
433

  
434
      if (maxw > surface.mRealWidth || maxh > surface.mRealHeight)
435
        {
436
        surface.mRealWidth = maxw;
437
        surface.mRealHeight = maxh;
438

  
439
        surface.recreate();
440
        surface.create();
441
        }
442
      }
443
    }
444

  
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

  
447
  private DistortedFramebuffer initializeBuffer(EffectQueuePostprocess queue, int fbo )
448
    {
449
    int currQuality = queue.getQuality();
450
    if( mBuffer[currQuality]==null ) createPostprocessingBuffers(currQuality, mWidth, mHeight, mNear);
451
    mBuffer[currQuality].setCurrFBO(fbo);
452

  
453
    if( !mBufferInitialized[currQuality] )
454
      {
455
      mBufferInitialized[currQuality] = true;
456
      clonePostprocessingViewportAndProjection(mBuffer[currQuality],this);
457
      }
458

  
459
    return mBuffer[currQuality];
460
    }
461

  
376 462
///////////////////////////////////////////////////////////////////////////////////////////////////
377 463
// Render all children, one by one. If there are no postprocessing effects, just render to THIS.
378 464
// Otherwise, render to a buffer and on each change of Postprocessing Bucket, apply the postprocessing
......
386 472
    DistortedFramebuffer buffer=null;
387 473
    EffectQueuePostprocess lastQueue=null, currQueue;
388 474
    long lastBucket=0, currBucket;
389
    boolean renderDirectly=false;
475
    boolean toThis=false;
390 476

  
391 477
    setCurrFBO(fbo);
392 478
    if( numChildren==0 ) setAsOutput(time);
393

  
394
    if( oit && numChildren>0 )
395
      {
396
      oitClear(this);
397
      }
479
    if( oit && numChildren>0 ) oitClear(this);
480
    for(int i=0; i<EffectQuality.LENGTH; i++) mBufferInitialized[i]=false;
398 481

  
399 482
    for(int i=0; i<numChildren; i++)
400 483
      {
......
402 485
      currQueue = (EffectQueuePostprocess)child.getEffects().getQueues()[3];
403 486
      currBucket= currQueue.getID();
404 487

  
405
      if( currBucket==0 )
488
      if( currBucket!=0 && lastBucket!=currBucket )
406 489
        {
407
        setAsOutput(time);
408

  
409
        if( oit )
410
          {
411
          numRenders += child.drawOIT(time, this);
412
          GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
413
          }
414
        else
415
          {
416
          numRenders += child.draw(time, this);
417
          }
490
        buffer = initializeBuffer(currQueue,fbo);
491
        if( lastBucket!=0 ) numRenders += accumulateAndBlit(lastQueue,children,buffer,bucketChange,i,false,time,fbo,oit);
492
        bucketChange= i;
493
        toThis = currQueue.getRenderDirectly();
418 494
        }
419
      else
420
        {
421
        int currQuality = currQueue.getQuality();
422

  
423
        if( mBuffer[currQuality]==null ) createPostprocessingBuffers(currQuality, mWidth, mHeight, mNear);
424
        mBuffer[currQuality].setCurrFBO(fbo);
425

  
426
        if( lastBucket!=currBucket )
427
          {
428
          if( lastBucket==0 )
429
            {
430
            clonePostprocessingViewportAndProjection(mBuffer[currQuality],this);
431
            }
432
          else
433
            {
434
            for(int j=bucketChange; j<i; j++)
435
              {
436
              DistortedNode node = children.getChild(j);
437

  
438
              if( node.getSurface().setAsInput() )
439
                {
440
                buffer.setAsOutput();
441
                numRenders += lastQueue.preprocess( buffer, node, buffer.mDistance, buffer.mMipmap, buffer.mProjectionMatrix );
442
                }
443
              }
444
            numRenders += lastQueue.postprocess(buffer);
445

  
446
            if( oit )
447
              {
448
              numRenders += oitBuild(time, buffer, fbo);
449
              GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
450
              }
451
            else
452
              {
453
              numRenders += blitWithDepth(time, buffer, fbo);
454
              }
455
            buffer.clearBuffer(fbo);
456
            }
457

  
458
          buffer= mBuffer[currQuality];
459
          bucketChange= i;
460
          renderDirectly = currQueue.getRenderDirectly();
461
          }
462

  
463
        if( renderDirectly )
464
          {
465
          setAsOutput(time);
466

  
467
          if( oit )
468
            {
469
            numRenders += child.drawOIT(time, this);
470
            GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
471
            }
472
          else
473
            {
474
            numRenders += child.draw(time, this);
475
            }
476
          }
477
        else
478
          {
479
          buffer.setAsOutput(time);
480
          child.drawNoBlend(time, buffer);
481
          }
482

  
483
        if( i==numChildren-1 )
484
          {
485
          for(int j=bucketChange; j<numChildren; j++)
486
            {
487
            DistortedNode node = children.getChild(j);
488

  
489
            if( node.getSurface().setAsInput() )
490
              {
491
              buffer.setAsOutput();
492
              numRenders += currQueue.preprocess( buffer, node, buffer.mDistance, buffer.mMipmap, buffer.mProjectionMatrix );
493
              }
494
            }
495
          numRenders += currQueue.postprocess(buffer);
496

  
497
          if( oit )
498
            {
499
            numRenders += oitBuild(time, buffer, fbo);
500
            GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
501
            buffer.clearBuffer(fbo);
502
            }
503
          else
504
            {
505
            numRenders += blitWithDepth(time, buffer,fbo);
506
            }
507
          }
508
        } // end else (postprocessed child)
495
      numRenders += renderChildToThisOrToBuffer(child,buffer,time,oit,currBucket==0 || toThis);
496
      if( currBucket!=0 && i==numChildren-1 ) numRenders += accumulateAndBlit(currQueue,children,buffer,bucketChange,numChildren,true,time,fbo,oit);
509 497

  
510 498
      lastQueue = currQueue;
511 499
      lastBucket= currBucket;
512
      } // end main for loop
513

  
514
    if( oit && numChildren>0 )
515
      {
516
      numRenders += oitRender(time, fbo);  // merge the OIT linked list
517 500
      }
518 501

  
502
    if( oit && numChildren>0 ) numRenders += oitRender(time, fbo);  // merge the OIT linked list
503

  
519 504
    return numRenders;
520 505
    }
521 506

  
......
979 964
    {
980 965
    return mHeight;
981 966
    }
982
}
967
}

Also available in: Unified diff