Revision 60c1c622
Added by Leszek Koltunski over 7 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.