Revision 178983f4
Added by Leszek Koltunski over 1 year ago
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
Remove the requirement that not-postprocessed children in the render scene must be in the first bucket.
Seriously simplify renderChildren().