Revision 60c1c622
Added by Leszek Koltunski over 8 years ago
| src/main/java/org/distorted/library/DistortedEffects.java | ||
|---|---|---|
| 297 | 297 |
|
| 298 | 298 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 299 | 299 |
|
| 300 |
DistortedFramebuffer getPostprocessingBuffer()
|
|
| 300 |
EffectQueuePostprocess getPostprocess()
|
|
| 301 | 301 |
{
|
| 302 |
return mP.mNumEffects==0 ? null : mP.mMainBuffer;
|
|
| 302 |
return mP; |
|
| 303 | 303 |
} |
| 304 | 304 |
|
| 305 | 305 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| src/main/java/org/distorted/library/DistortedFramebuffer.java | ||
|---|---|---|
| 31 | 31 |
public class DistortedFramebuffer extends DistortedOutputSurface implements DistortedInputSurface |
| 32 | 32 |
{
|
| 33 | 33 |
|
| 34 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 35 |
|
|
| 36 |
DistortedFramebuffer getBuffer() |
|
| 37 |
{
|
|
| 38 |
return this; |
|
| 39 |
} |
|
| 40 |
|
|
| 41 | 34 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 42 | 35 |
// Must be called from a thread holding OpenGL Context |
| 43 | 36 |
// Watch out - this has the side-effect of binding a Texture and a Framebuffer! |
| ... | ... | |
| 135 | 128 |
if( mDepthCreated!=DONT_CREATE ) mDepthCreated = NOT_CREATED_YET; |
| 136 | 129 |
} |
| 137 | 130 |
|
| 138 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 139 |
// if new size fits into the size of the underlying Texture, just change the projection without |
|
| 140 |
// reallocating the Texture. Otherwise, we need to reallocate. |
|
| 141 |
// |
|
| 142 |
// Must be called from a thread holding the OpenGL context. |
|
| 143 |
|
|
| 144 |
void resizeFast(int width, int height) |
|
| 145 |
{
|
|
| 146 |
if( mWidth!=width || mHeight!=height ) |
|
| 147 |
{
|
|
| 148 |
mWidth = width; |
|
| 149 |
mHeight= height; |
|
| 150 |
createProjection(); |
|
| 151 |
|
|
| 152 |
if( width> mSizeX || height> mSizeY) |
|
| 153 |
{
|
|
| 154 |
mSizeX = width; |
|
| 155 |
mSizeY = height; |
|
| 156 |
delete(); |
|
| 157 |
} |
|
| 158 |
} |
|
| 159 |
|
|
| 160 |
create(); |
|
| 161 |
} |
|
| 162 |
|
|
| 163 | 131 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 164 | 132 |
// create SYSTEM or TREE framebuffers (those are just like normal FBOs, just hold information |
| 165 | 133 |
// that they were autocreated only for the Library's internal purposes (SYSTEM) or for using |
| src/main/java/org/distorted/library/DistortedNode.java | ||
|---|---|---|
| 220 | 220 |
|
| 221 | 221 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 222 | 222 |
|
| 223 |
DistortedFramebuffer getPostprocessingBuffer()
|
|
| 223 |
EffectQueuePostprocess getPostprocess()
|
|
| 224 | 224 |
{
|
| 225 |
return mEffects.getPostprocessingBuffer();
|
|
| 225 |
return mEffects.getPostprocess(); |
|
| 226 | 226 |
} |
| 227 | 227 |
|
| 228 | 228 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| src/main/java/org/distorted/library/DistortedOutputSurface.java | ||
|---|---|---|
| 30 | 30 |
private ArrayList<DistortedNode> mChildren; |
| 31 | 31 |
private int mNumChildren; // ==mChildren.length(), but we only create mChildren if the first one gets added |
| 32 | 32 |
|
| 33 |
DistortedFramebuffer mBuffer1, mBuffer2; |
|
| 34 |
|
|
| 33 | 35 |
private long mTime; |
| 34 | 36 |
private float mFOV; |
| 35 | 37 |
int mWidth,mHeight,mDepth; |
| ... | ... | |
| 43 | 45 |
private float mClearR, mClearG, mClearB, mClearA; |
| 44 | 46 |
private float mClearDepth; |
| 45 | 47 |
|
| 46 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 47 |
|
|
| 48 |
abstract DistortedFramebuffer getBuffer(); |
|
| 49 |
|
|
| 50 | 48 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 51 | 49 |
|
| 52 | 50 |
DistortedOutputSurface(int width, int height, int createColor, int createDepth, int fbo, int type) |
| ... | ... | |
| 123 | 121 |
{
|
| 124 | 122 |
int numRenders = 0; |
| 125 | 123 |
DistortedNode child; |
| 126 |
DistortedFramebuffer fbo;
|
|
| 127 |
DistortedOutputSurface surface;
|
|
| 124 |
EffectQueuePostprocess lastP=null, currP=null;
|
|
| 125 |
long lastB=0, currB=0;
|
|
| 128 | 126 |
|
| 129 |
// 1. Render all children that have postprocessing effects to their own buffer FBOs |
|
| 127 |
// Render all children, one by one. |
|
| 128 |
// If there are no postprocessing effects, just render to THIS. |
|
| 129 |
// Otherwise, render to a buffer and on each change of Postprocessing Bucket, |
|
| 130 |
// apply the postprocessing to a whole buffer and merge it. |
|
| 131 |
// |
|
| 132 |
// TODO: in order for this to be efficient, the children really need to be sorted |
|
| 133 |
// to keep the same Buckets together. |
|
| 130 | 134 |
|
| 131 | 135 |
for(int i=0; i<num; i++) |
| 132 | 136 |
{
|
| 133 | 137 |
child = children.get(i); |
| 134 |
fbo = child.getPostprocessingBuffer(); |
|
| 138 |
currP = child.getPostprocess(); |
|
| 139 |
currB = currP.getBucket(); |
|
| 135 | 140 |
|
| 136 |
if( fbo!=null )
|
|
| 141 |
if( i>0 && currB!=lastB )
|
|
| 137 | 142 |
{
|
| 138 |
fbo.resizeFast(mWidth,mHeight); |
|
| 139 |
numRenders += child.draw(time,fbo); |
|
| 143 |
numRenders += lastP.postprocess(time,this); |
|
| 140 | 144 |
} |
| 141 |
} |
|
| 142 |
|
|
| 143 |
// 2. If we have rendered anything so far, and we are a Screen, then render to an |
|
| 144 |
// intermediate FBO instead. |
|
| 145 |
|
|
| 146 |
surface = this;//numRenders>0 ? getBuffer() : this; |
|
| 147 |
|
|
| 148 |
// 3. Render all children without postprocessing effects to buffer |
|
| 149 |
|
|
| 150 |
for(int i=0; i<num; i++) |
|
| 151 |
{
|
|
| 152 |
child = children.get(i); |
|
| 153 |
fbo = child.getPostprocessingBuffer(); |
|
| 154 | 145 |
|
| 155 |
if( fbo==null )
|
|
| 146 |
if( currB==0 )
|
|
| 156 | 147 |
{
|
| 157 |
numRenders += child.draw(time,surface);
|
|
| 148 |
numRenders += child.draw(time,this);
|
|
| 158 | 149 |
} |
| 159 |
} |
|
| 150 |
else |
|
| 151 |
{
|
|
| 152 |
if( mBuffer1==null ) |
|
| 153 |
{
|
|
| 154 |
mBuffer1 = new DistortedFramebuffer(mDepthCreated!=DONT_CREATE, DistortedSurface.TYPE_TREE, mWidth, mHeight); |
|
| 155 |
mBuffer2 = new DistortedFramebuffer(false , DistortedSurface.TYPE_TREE, mWidth, mHeight); |
|
| 156 |
} |
|
| 160 | 157 |
|
| 161 |
// 4. For all postprocessing fbo, |
|
| 162 |
// postprocess fbo |
|
| 163 |
// merge to buffer |
|
| 158 |
numRenders += child.draw(time,mBuffer1); |
|
| 159 |
} |
|
| 164 | 160 |
|
| 165 |
for(int i=0; i<num; i++) |
|
| 166 |
{
|
|
| 167 |
numRenders += children.get(i).postprocess(time,surface); |
|
| 161 |
lastP = currP; |
|
| 162 |
lastB = currB; |
|
| 168 | 163 |
} |
| 169 | 164 |
|
| 170 |
// 5. finally blit to this if we have to |
|
| 171 |
|
|
| 172 |
if( surface!=this && ((DistortedFramebuffer)surface).setAsInput() ) |
|
| 165 |
if( currB!=0 ) |
|
| 173 | 166 |
{
|
| 174 |
numRenders++; |
|
| 175 |
DistortedEffects.blitPriv(this); |
|
| 167 |
numRenders += currP.postprocess(time,this); |
|
| 176 | 168 |
} |
| 177 | 169 |
|
| 178 | 170 |
return numRenders; |
| src/main/java/org/distorted/library/DistortedScreen.java | ||
|---|---|---|
| 27 | 27 |
*/ |
| 28 | 28 |
public class DistortedScreen extends DistortedOutputSurface |
| 29 | 29 |
{
|
| 30 |
private DistortedFramebuffer mBuffer = null; |
|
| 31 | 30 |
|
| 32 | 31 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 33 | 32 |
// here we don't manage underlying OpenGL assets ourselves |
| ... | ... | |
| 36 | 35 |
void delete() {}
|
| 37 | 36 |
void recreate() {}
|
| 38 | 37 |
|
| 39 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 40 |
|
|
| 41 |
DistortedFramebuffer getBuffer() |
|
| 42 |
{
|
|
| 43 |
if( mBuffer==null ) |
|
| 44 |
{
|
|
| 45 |
mBuffer = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,mWidth,mHeight); |
|
| 46 |
} |
|
| 47 |
|
|
| 48 |
if( mBuffer.mWidth != mWidth || mBuffer.mHeight != mHeight ) |
|
| 49 |
{
|
|
| 50 |
mBuffer.resizeFast(mWidth,mHeight); |
|
| 51 |
} |
|
| 52 |
|
|
| 53 |
return mBuffer; |
|
| 54 |
} |
|
| 55 |
|
|
| 56 | 38 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 57 | 39 |
// PUBLIC API |
| 58 | 40 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| src/main/java/org/distorted/library/EffectQueuePostprocess.java | ||
|---|---|---|
| 65 | 65 |
mQuadTexture.put(textureNor).position(0); |
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 |
private static DistortedFramebuffer mPostBuffer = new DistortedFramebuffer(true,DistortedSurface.TYPE_SYST,1,1); |
|
| 69 |
DistortedFramebuffer mMainBuffer = new DistortedFramebuffer(true,DistortedSurface.TYPE_TREE,1,1); |
|
| 70 |
|
|
| 71 | 68 |
// BLUR effect |
| 72 | 69 |
private static final float GAUSSIAN[] = // G(0.00), G(0.03), G(0.06), ..., G(3.00), 0 |
| 73 | 70 |
{ // where G(x)= (1/(sqrt(2*PI))) * e^(-(x^2)/2). The last 0 terminates.
|
| ... | ... | |
| 162 | 159 |
} |
| 163 | 160 |
|
| 164 | 161 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 165 |
|
|
| 162 |
// TODO: change this into a EQP <--> long Map. |
|
| 163 |
// For now, just returning number of effects is sufficient. |
|
| 164 |
|
|
| 165 |
long getBucket() |
|
| 166 |
{
|
|
| 167 |
return mNumEffects; |
|
| 168 |
} |
|
| 169 |
|
|
| 170 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 171 |
|
|
| 166 | 172 |
synchronized boolean compute(long currTime) |
| 167 | 173 |
{
|
| 168 | 174 |
if( currTime==mTime ) return false; |
| ... | ... | |
| 260 | 266 |
{
|
| 261 | 267 |
if( mNumEffects>0 && compute(time) ) |
| 262 | 268 |
{
|
| 263 |
mMainBuffer.setAsInput();
|
|
| 269 |
surface.mBuffer1.setAsInput();
|
|
| 264 | 270 |
float w = surface.mWidth; |
| 265 | 271 |
float h = surface.mHeight; |
| 266 | 272 |
|
| ... | ... | |
| 275 | 281 |
|
| 276 | 282 |
// horizontal blur |
| 277 | 283 |
mBlur1Program.useProgram(); |
| 278 |
mPostBuffer.resizeFast( (int)w, (int)h); |
|
| 279 |
mPostBuffer.setAsOutput(time); |
|
| 284 |
surface.mBuffer2.setAsOutput(time); |
|
| 280 | 285 |
|
| 281 | 286 |
GLES30.glUniform1fv( mWeights1H, radius+1, weightsCache,offset); |
| 282 | 287 |
GLES30.glUniform1i( mRadius1H, radius); |
| ... | ... | |
| 290 | 295 |
|
| 291 | 296 |
// vertical blur |
| 292 | 297 |
mBlur2Program.useProgram(); |
| 293 |
mPostBuffer.setAsInput();
|
|
| 294 |
mMainBuffer.setAsDepth();
|
|
| 298 |
surface.mBuffer2.setAsInput();
|
|
| 299 |
surface.mBuffer1.setAsDepth();
|
|
| 295 | 300 |
surface.setAsOutput(time); |
| 296 | 301 |
|
| 297 | 302 |
GLES30.glUniform1fv( mWeights2H, radius+1, weightsCache,offset); |
Also available in: Unified diff
Move the Postprocessing buffers to OutputSurface.