41 |
41 |
*/
|
42 |
42 |
public class DistortedFramebuffer
|
43 |
43 |
{
|
44 |
|
private static final int TEXTURE_FAILED_TO_CREATE = -1;
|
45 |
|
private static final int TEXTURE_NOT_CREATED_YET = -2;
|
46 |
|
private static final int TEXTURE_DONT_CREATE = -3;
|
|
44 |
private static final int FAILED_TO_CREATE = -1;
|
|
45 |
private static final int NOT_CREATED_YET = -2;
|
|
46 |
private static final int DONT_CREATE = -3;
|
47 |
47 |
|
48 |
48 |
private static boolean mListMarked = false;
|
49 |
49 |
private static LinkedList<DistortedFramebuffer> mList = new LinkedList<>();
|
50 |
50 |
|
51 |
|
private int[] texIds = new int[1];
|
52 |
|
private int[] fboIds = new int[1];
|
|
51 |
private int[] colorIds = new int[1];
|
|
52 |
private int[] depthIds = new int[1];
|
|
53 |
private int[] fboIds = new int[1];
|
53 |
54 |
|
54 |
55 |
private boolean mMarked;
|
|
56 |
private boolean mDepthWanted;
|
55 |
57 |
|
56 |
58 |
// Projection stuff
|
57 |
59 |
private float mX, mY, mFOV;
|
... | ... | |
64 |
66 |
|
65 |
67 |
boolean createFBO()
|
66 |
68 |
{
|
67 |
|
if( texIds[0]==TEXTURE_NOT_CREATED_YET )
|
|
69 |
if( colorIds[0]==NOT_CREATED_YET )
|
68 |
70 |
{
|
69 |
|
GLES20.glGenTextures(1, texIds, 0);
|
70 |
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texIds[0]);
|
|
71 |
GLES20.glGenTextures(1, colorIds, 0);
|
|
72 |
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, colorIds[0]);
|
71 |
73 |
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
|
72 |
74 |
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
|
73 |
75 |
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
|
... | ... | |
76 |
78 |
|
77 |
79 |
GLES20.glGenFramebuffers(1, fboIds, 0);
|
78 |
80 |
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
|
79 |
|
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texIds[0], 0);
|
|
81 |
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, colorIds[0], 0);
|
80 |
82 |
|
81 |
83 |
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
|
82 |
84 |
|
83 |
85 |
if(status != GLES20.GL_FRAMEBUFFER_COMPLETE)
|
84 |
86 |
{
|
85 |
87 |
android.util.Log.e("DistortedFramebuffer", "failed to create framebuffer, error="+status);
|
86 |
|
GLES20.glDeleteTextures(1, texIds, 0);
|
|
88 |
GLES20.glDeleteTextures(1, colorIds, 0);
|
87 |
89 |
GLES20.glDeleteFramebuffers(1, fboIds, 0);
|
88 |
|
fboIds[0] = 0;
|
89 |
|
texIds[0] = TEXTURE_FAILED_TO_CREATE;
|
|
90 |
fboIds[0] = 0;
|
|
91 |
colorIds[0] = FAILED_TO_CREATE;
|
90 |
92 |
return false;
|
91 |
93 |
}
|
92 |
94 |
|
... | ... | |
94 |
96 |
//android.util.Log.e("FBO", "created ("+mWidth+","+mHeight+") "+fboIds[0]);
|
95 |
97 |
}
|
96 |
98 |
|
|
99 |
if( mDepthWanted && depthIds[0]==NOT_CREATED_YET ) // we need to create a new DEPTH attachment
|
|
100 |
{
|
|
101 |
GLES20.glGenTextures(1, depthIds, 0);
|
|
102 |
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, depthIds[0]);
|
|
103 |
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
|
|
104 |
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
|
|
105 |
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
|
|
106 |
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
|
|
107 |
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_DEPTH_COMPONENT, mWidth, mHeight, 0, GLES20.GL_DEPTH_COMPONENT, GLES20.GL_FLOAT, null);
|
|
108 |
|
|
109 |
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
|
|
110 |
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_TEXTURE_2D, depthIds[0], 0);
|
|
111 |
|
|
112 |
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
|
|
113 |
|
|
114 |
if(status != GLES20.GL_FRAMEBUFFER_COMPLETE)
|
|
115 |
{
|
|
116 |
android.util.Log.e("DistortedFramebuffer", "failed to create depth, error="+status);
|
|
117 |
GLES20.glDeleteTextures(1, colorIds, 0);
|
|
118 |
GLES20.glDeleteFramebuffers(1, fboIds, 0);
|
|
119 |
fboIds[0] = 0;
|
|
120 |
depthIds[0] = FAILED_TO_CREATE;
|
|
121 |
return false;
|
|
122 |
}
|
|
123 |
}
|
|
124 |
if( !mDepthWanted && depthIds[0]!=NOT_CREATED_YET ) // we need to detach and destroy the DEPTH attachment.
|
|
125 |
{
|
|
126 |
GLES20.glDeleteTextures(1, depthIds, 0);
|
|
127 |
depthIds[0]=NOT_CREATED_YET;
|
|
128 |
}
|
|
129 |
|
97 |
130 |
return true;
|
98 |
131 |
}
|
99 |
132 |
|
... | ... | |
102 |
135 |
|
103 |
136 |
private void deleteFBO()
|
104 |
137 |
{
|
105 |
|
if( texIds[0]>=0 )
|
|
138 |
if( colorIds[0]>=0 )
|
106 |
139 |
{
|
107 |
140 |
//android.util.Log.e("FBO", "deleting ("+mWidth+","+mHeight+") "+fboIds[0]);
|
108 |
141 |
|
109 |
|
GLES20.glDeleteTextures(1, texIds, 0);
|
110 |
|
GLES20.glDeleteFramebuffers(1, fboIds, 0);
|
|
142 |
if( depthIds[0]>=0 )
|
|
143 |
{
|
|
144 |
GLES20.glDeleteTextures(1, depthIds, 0);
|
|
145 |
depthIds[0]=NOT_CREATED_YET;
|
|
146 |
}
|
|
147 |
|
|
148 |
GLES20.glDeleteTextures(1, colorIds, 0);
|
|
149 |
colorIds[0] = NOT_CREATED_YET;
|
111 |
150 |
|
|
151 |
GLES20.glDeleteFramebuffers(1, fboIds, 0);
|
112 |
152 |
fboIds[0] = 0;
|
113 |
|
texIds[0] = TEXTURE_NOT_CREATED_YET;
|
114 |
153 |
}
|
115 |
154 |
|
116 |
155 |
mMarked = false;
|
... | ... | |
120 |
159 |
|
121 |
160 |
void reset()
|
122 |
161 |
{
|
123 |
|
if( texIds[0]!=TEXTURE_DONT_CREATE)
|
124 |
|
texIds[0] = TEXTURE_NOT_CREATED_YET;
|
|
162 |
if( colorIds[0]!=DONT_CREATE )
|
|
163 |
colorIds[0] = NOT_CREATED_YET;
|
|
164 |
|
|
165 |
if( mDepthWanted ) depthIds[0] = NOT_CREATED_YET;
|
125 |
166 |
}
|
126 |
167 |
|
127 |
168 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
... | ... | |
129 |
170 |
void setAsOutput()
|
130 |
171 |
{
|
131 |
172 |
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
|
|
173 |
|
|
174 |
if( depthIds[0]!=NOT_CREATED_YET )
|
|
175 |
{
|
|
176 |
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
|
|
177 |
GLES20.glDepthMask(true);
|
|
178 |
}
|
|
179 |
else
|
|
180 |
{
|
|
181 |
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
|
|
182 |
GLES20.glDepthMask(false);
|
|
183 |
}
|
132 |
184 |
}
|
133 |
185 |
|
134 |
186 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
135 |
187 |
|
136 |
188 |
void setAsInput()
|
137 |
189 |
{
|
138 |
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texIds[0]);
|
|
190 |
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, colorIds[0]);
|
139 |
191 |
}
|
140 |
192 |
|
141 |
193 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
... | ... | |
227 |
279 |
{
|
228 |
280 |
mProjectionMatrix = new float[16];
|
229 |
281 |
|
230 |
|
mHeight = height;
|
231 |
|
mWidth = width;
|
232 |
|
fboIds[0]= -1;
|
233 |
|
texIds[0]= TEXTURE_NOT_CREATED_YET;
|
234 |
|
mFOV = 60.0f;
|
235 |
|
mX = 0.0f;
|
236 |
|
mY = 0.0f;
|
237 |
|
mMarked = false;
|
|
282 |
mHeight = height;
|
|
283 |
mWidth = width;
|
|
284 |
mFOV = 60.0f;
|
|
285 |
mX = 0.0f;
|
|
286 |
mY = 0.0f;
|
|
287 |
mMarked = false;
|
|
288 |
mDepthWanted= false;
|
|
289 |
|
|
290 |
fboIds[0] =-1;
|
|
291 |
colorIds[0]= NOT_CREATED_YET;
|
|
292 |
depthIds[0]= NOT_CREATED_YET;
|
238 |
293 |
|
239 |
294 |
createProjection();
|
240 |
295 |
}
|
... | ... | |
251 |
306 |
{
|
252 |
307 |
mProjectionMatrix = new float[16];
|
253 |
308 |
|
254 |
|
fboIds[0]= fbo;
|
255 |
|
texIds[0]= TEXTURE_DONT_CREATE;
|
256 |
|
mFOV = 60.0f;
|
257 |
|
mX = 0.0f;
|
258 |
|
mY = 0.0f;
|
259 |
|
mMarked = false;
|
|
309 |
mFOV = 60.0f;
|
|
310 |
mX = 0.0f;
|
|
311 |
mY = 0.0f;
|
|
312 |
mMarked = false;
|
|
313 |
mDepthWanted= true;
|
|
314 |
|
|
315 |
fboIds[0] = fbo;
|
|
316 |
colorIds[0]= DONT_CREATE;
|
|
317 |
depthIds[0]= DONT_CREATE;
|
|
318 |
}
|
|
319 |
|
|
320 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
321 |
/**
|
|
322 |
* Create a new DEPTH buffer and attach it or (param=false) detach an existing DEPTh attachment and destroy it.
|
|
323 |
*
|
|
324 |
* @param hasDepthAttachment <bold>true</bold> if we want to attach a new DEPTH buffer to the FBO.<br>
|
|
325 |
* <bold>false</bold> if we want to detach the DEPTH attachment.
|
|
326 |
*/
|
|
327 |
public void setDepthAttachment(boolean hasDepthAttachment)
|
|
328 |
{
|
|
329 |
mDepthWanted = hasDepthAttachment;
|
260 |
330 |
}
|
261 |
331 |
|
262 |
332 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
333 |
|
263 |
334 |
/**
|
264 |
335 |
* Draw the (texture,mesh,effects) object to the Framebuffer.
|
265 |
336 |
* <p>
|
... | ... | |
275 |
346 |
tex.createTexture();
|
276 |
347 |
tex.setAsInput();
|
277 |
348 |
createFBO();
|
278 |
|
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
|
|
349 |
setAsOutput();
|
279 |
350 |
effects.drawPriv(tex.mHalfX, tex.mHalfY, mesh, this, time);
|
280 |
351 |
DistortedFramebuffer.deleteAllMarked();
|
281 |
352 |
DistortedTexture.deleteAllMarked();
|
... | ... | |
298 |
369 |
{
|
299 |
370 |
fbo.createFBO();
|
300 |
371 |
|
301 |
|
if( fbo.texIds[0]>0 ) // fbo created with the first constructor
|
|
372 |
if( fbo.colorIds[0]>0 ) // fbo created with the first constructor
|
302 |
373 |
{
|
303 |
374 |
createFBO();
|
304 |
|
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
|
305 |
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fbo.texIds[0]);
|
|
375 |
setAsOutput();
|
|
376 |
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fbo.colorIds[0]);
|
306 |
377 |
effects.drawPriv(fbo.mWidth/2, fbo.mHeight/2, mesh, this, time);
|
307 |
378 |
DistortedFramebuffer.deleteAllMarked();
|
308 |
379 |
DistortedTexture.deleteAllMarked();
|
... | ... | |
321 |
392 |
public void renderTo(DistortedTree dt, long time)
|
322 |
393 |
{
|
323 |
394 |
createFBO();
|
324 |
|
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
|
|
395 |
setAsOutput();
|
325 |
396 |
dt.drawRecursive(time,this);
|
326 |
397 |
DistortedFramebuffer.deleteAllMarked();
|
327 |
398 |
DistortedTexture.deleteAllMarked();
|
... | ... | |
379 |
450 |
|
380 |
451 |
createProjection();
|
381 |
452 |
|
382 |
|
if( texIds[0]>0 ) markForDeletion();
|
|
453 |
if( colorIds[0]>0 ) markForDeletion();
|
383 |
454 |
}
|
384 |
455 |
}
|
385 |
456 |
|
... | ... | |
396 |
467 |
*/
|
397 |
468 |
public int getTextureID()
|
398 |
469 |
{
|
399 |
|
return texIds[0];
|
|
470 |
return colorIds[0];
|
|
471 |
}
|
|
472 |
|
|
473 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
474 |
/**
|
|
475 |
* Return true if the FBO contains a DEPTH attachment.
|
|
476 |
*
|
|
477 |
* @return <bold>true</bold> if the FBO contains a DEPTH attachment.
|
|
478 |
*/
|
|
479 |
public boolean hasDepth()
|
|
480 |
{
|
|
481 |
return mDepthWanted;
|
400 |
482 |
}
|
401 |
483 |
}
|
First attempt at making it possible to dynamically add and remove DEPTH attachments from an FBO.