| 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.