Revision c5369f1b
Added by Leszek Koltunski almost 8 years ago
src/main/java/org/distorted/library/DistortedEffects.java | ||
---|---|---|
183 | 183 |
// DEBUG ONLY |
184 | 184 |
|
185 | 185 |
@SuppressWarnings("unused") |
186 |
private void displayBoundingRect(float halfX, float halfY, float halfZ, DistortedFramebuffer df, float[] mvp, float[] vertices)
|
|
186 |
private void displayBoundingRect(float halfX, float halfY, float halfZ, DistortedOutputSurface surface, float[] mvp, float[] vertices)
|
|
187 | 187 |
{ |
188 | 188 |
int len = vertices.length/3; |
189 | 189 |
int minx = Integer.MAX_VALUE; |
... | ... | |
194 | 194 |
|
195 | 195 |
float x,y,z, X,Y,W, ndcX,ndcY; |
196 | 196 |
|
197 |
DistortedProjection projection = surface.getProjection(); |
|
198 |
|
|
197 | 199 |
for(int i=0; i<len; i++) |
198 | 200 |
{ |
199 | 201 |
x = 2*halfX*vertices[3*i ]; |
... | ... | |
207 | 209 |
ndcX = X/W; |
208 | 210 |
ndcY = Y/W; |
209 | 211 |
|
210 |
wx = (int)(df.mWidth *(ndcX+1)/2);
|
|
211 |
wy = (int)(df.mHeight*(ndcY+1)/2);
|
|
212 |
wx = (int)(projection.mWidth *(ndcX+1)/2);
|
|
213 |
wy = (int)(projection.mHeight*(ndcY+1)/2);
|
|
212 | 214 |
|
213 | 215 |
if( wx<minx ) minx = wx; |
214 | 216 |
if( wx>maxx ) maxx = wx; |
... | ... | |
217 | 219 |
} |
218 | 220 |
|
219 | 221 |
mDebugProgram.useProgram(); |
220 |
df.setAsOutput();
|
|
222 |
surface.setAsOutput();
|
|
221 | 223 |
|
222 | 224 |
Matrix.setIdentityM( mTmpMatrix, 0); |
223 |
Matrix.translateM ( mTmpMatrix, 0, minx-df.mWidth/2, maxy-df.mHeight/2, -df.mDistance);
|
|
225 |
Matrix.translateM ( mTmpMatrix, 0, minx-projection.mWidth/2, maxy-projection.mHeight/2, -projection.mDistance);
|
|
224 | 226 |
Matrix.scaleM ( mTmpMatrix, 0, (float)(maxx-minx)/(2*halfX), (float)(maxy-miny)/(2*halfY), 1.0f); |
225 | 227 |
Matrix.translateM ( mTmpMatrix, 0, halfX,-halfY, 0); |
226 |
Matrix.multiplyMM ( mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
228 |
Matrix.multiplyMM ( mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
227 | 229 |
|
228 | 230 |
GLES30.glUniform2f( mObjDH , 2*halfX, 2*halfY); |
229 | 231 |
GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0); |
... | ... | |
234 | 236 |
|
235 | 237 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
236 | 238 |
|
237 |
void drawPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df, long currTime)
|
|
239 |
void drawPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedOutputSurface surface, long currTime)
|
|
238 | 240 |
{ |
239 | 241 |
mM.compute(currTime); |
240 | 242 |
mV.compute(currTime); |
... | ... | |
242 | 244 |
mP.compute(currTime); |
243 | 245 |
|
244 | 246 |
float halfZ = halfInputW*mesh.zFactor; |
245 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight); |
|
247 |
DistortedProjection projection = surface.getProjection(); |
|
248 |
GLES30.glViewport(0, 0, projection.mWidth, projection.mHeight); |
|
246 | 249 |
|
247 | 250 |
if( mP.mNumEffects==0 ) |
248 | 251 |
{ |
249 | 252 |
mProgram.useProgram(); |
250 |
df.setAsOutput();
|
|
251 |
mM.send(df,halfInputW,halfInputH,halfZ);
|
|
253 |
surface.setAsOutput();
|
|
254 |
mM.send(projection,halfInputW,halfInputH,halfZ);
|
|
252 | 255 |
mV.send(halfInputW,halfInputH,halfZ); |
253 | 256 |
mF.send(halfInputW,halfInputH); |
254 | 257 |
GLES30.glVertexAttribPointer(mProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions); |
... | ... | |
260 | 263 |
{ |
261 | 264 |
if( mV.mNumEffects==0 && mF.mNumEffects==0 && (mesh instanceof MeshFlat) && mM.canUseShortcut() ) |
262 | 265 |
{ |
263 |
mM.constructMatrices(df,halfInputW,halfInputH);
|
|
264 |
mP.render(2*halfInputW, 2*halfInputH, mM.getMVP(), df);
|
|
266 |
mM.constructMatrices(projection,halfInputW,halfInputH);
|
|
267 |
mP.render(2*halfInputW, 2*halfInputH, mM.getMVP(), surface);
|
|
265 | 268 |
} |
266 | 269 |
else |
267 | 270 |
{ |
268 | 271 |
mProgram.useProgram(); |
269 |
mBufferFBO.resizeFast(df.mWidth, df.mHeight);
|
|
272 |
mBufferFBO.resizeFast(projection.mWidth, projection.mHeight);
|
|
270 | 273 |
mBufferFBO.setAsOutput(); |
271 | 274 |
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
272 | 275 |
GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT); |
273 |
mM.send(mBufferFBO,halfInputW,halfInputH,halfZ); |
|
276 |
mM.send(mBufferFBO.getProjection(),halfInputW,halfInputH,halfZ);
|
|
274 | 277 |
mV.send(halfInputW,halfInputH,halfZ); |
275 | 278 |
mF.send(halfInputW,halfInputH); |
276 | 279 |
GLES30.glVertexAttribPointer(mProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions); |
... | ... | |
279 | 282 |
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.dataLength); |
280 | 283 |
|
281 | 284 |
Matrix.setIdentityM(mTmpMatrix, 0); |
282 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -df.mDistance);
|
|
283 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
285 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -projection.mDistance);
|
|
286 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
284 | 287 |
|
285 | 288 |
mBufferFBO.setAsInput(); |
286 |
mP.render(df.mWidth, df.mHeight, mMVPMatrix, df);
|
|
289 |
mP.render(projection.mWidth, projection.mHeight, mMVPMatrix, surface);
|
|
287 | 290 |
} |
288 | 291 |
} |
289 | 292 |
|
... | ... | |
294 | 297 |
|
295 | 298 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
296 | 299 |
|
297 |
static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df)
|
|
300 |
static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedProjection projection)
|
|
298 | 301 |
{ |
299 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight);
|
|
302 |
GLES30.glViewport(0, 0, projection.mWidth, projection.mHeight);
|
|
300 | 303 |
|
301 | 304 |
Matrix.setIdentityM(mTmpMatrix, 0); |
302 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -df.mDistance);
|
|
303 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
305 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -projection.mDistance);
|
|
306 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
304 | 307 |
|
305 |
EffectQueueMatrix.sendZero(df,halfInputW,halfInputH,halfInputW*mesh.zFactor);
|
|
308 |
EffectQueueMatrix.sendZero(projection,halfInputW,halfInputH,halfInputW*mesh.zFactor);
|
|
306 | 309 |
EffectQueueVertex.sendZero(); |
307 | 310 |
EffectQueueFragment.sendZero(); |
308 | 311 |
|
src/main/java/org/distorted/library/DistortedFramebuffer.java | ||
---|---|---|
20 | 20 |
package org.distorted.library; |
21 | 21 |
|
22 | 22 |
import android.opengl.GLES30; |
23 |
import android.opengl.Matrix; |
|
24 | 23 |
|
25 | 24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
26 | 25 |
/** |
27 | 26 |
* Class which represents a OpenGL Framebuffer object. |
28 | 27 |
* <p> |
29 |
* User is able to create either Framebuffers from objects already constructed outside |
|
30 |
* of the library (the first constructor; primary use case: the screen) or an offscreen |
|
31 |
* FBOs. |
|
32 |
* <p> |
|
33 |
* Keep all objects created in a static LinkedList. The point: we need to be able to mark |
|
34 |
* Framebuffers for deletion, and delete all marked objects later at a convenient time (that's |
|
35 |
* because we can only delete from a thread that holds the OpenGL context so here we provide a |
|
36 |
* framework where one is able to mark for deletion at any time and actual deletion takes place |
|
37 |
* on the next render). |
|
28 |
* User is able to create offscreen FBOs and both a) render to them b) use their COLOR0 attachment as |
|
29 |
* an input texture. |
|
38 | 30 |
*/ |
39 |
public class DistortedFramebuffer extends DistortedRenderable |
|
31 |
public class DistortedFramebuffer extends DistortedRenderable implements DistortedInputSurface, DistortedOutputSurface
|
|
40 | 32 |
{ |
41 | 33 |
private int[] mDepthH = new int[1]; |
42 | 34 |
private int[] mFBOH = new int[1]; |
43 |
|
|
44 | 35 |
private boolean mDepthEnabled; |
45 |
|
|
46 |
// Projection stuff |
|
47 |
private float mX, mY, mFOV; |
|
48 |
int mWidth,mHeight,mDepth; |
|
49 |
float mDistance; |
|
50 |
float[] mProjectionMatrix; |
|
36 |
private DistortedProjection mProjection; |
|
51 | 37 |
|
52 | 38 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
53 | 39 |
// Must be called from a thread holding OpenGL Context |
54 | 40 |
// Watch out - this has the side-effect of binding a Texture and a Framebuffer! |
55 | 41 |
|
56 |
void create() |
|
42 |
public void create()
|
|
57 | 43 |
{ |
58 | 44 |
if( mColorH[0]==NOT_CREATED_YET ) |
59 | 45 |
{ |
... | ... | |
146 | 132 |
if( mDepthEnabled ) mDepthH[0] = NOT_CREATED_YET; |
147 | 133 |
} |
148 | 134 |
|
149 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
150 |
|
|
151 |
void setAsOutput() |
|
152 |
{ |
|
153 |
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]); |
|
154 |
|
|
155 |
if( mDepthH[0]!=NOT_CREATED_YET ) |
|
156 |
{ |
|
157 |
GLES30.glEnable(GLES30.GL_DEPTH_TEST); |
|
158 |
GLES30.glDepthMask(true); |
|
159 |
} |
|
160 |
else |
|
161 |
{ |
|
162 |
GLES30.glDisable(GLES30.GL_DEPTH_TEST); |
|
163 |
GLES30.glDepthMask(false); |
|
164 |
} |
|
165 |
} |
|
166 |
|
|
167 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
168 |
|
|
169 |
private void createProjection() |
|
170 |
{ |
|
171 |
if( mWidth>0 && mHeight>1 ) |
|
172 |
{ |
|
173 |
if( mFOV>0.0f ) // perspective projection |
|
174 |
{ |
|
175 |
float left = (-mX-mWidth /2.0f)/mHeight; |
|
176 |
float right = (-mX+mWidth /2.0f)/mHeight; |
|
177 |
float bottom = (-mY-mHeight/2.0f)/mHeight; |
|
178 |
float top = (-mY+mHeight/2.0f)/mHeight; |
|
179 |
float near = (top-bottom) / (2.0f*(float)Math.tan(mFOV*Math.PI/360)); |
|
180 |
mDistance = mHeight*near/(top-bottom); |
|
181 |
float far = 2*mDistance-near; |
|
182 |
mDepth = (int)((far-near)/2); |
|
183 |
|
|
184 |
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
185 |
} |
|
186 |
else // parallel projection |
|
187 |
{ |
|
188 |
float left = -mX-mWidth /2.0f; |
|
189 |
float right = -mX+mWidth /2.0f; |
|
190 |
float bottom = -mY-mHeight/2.0f; |
|
191 |
float top = -mY+mHeight/2.0f; |
|
192 |
float near = (mWidth+mHeight)/2; |
|
193 |
mDistance = 2*near; |
|
194 |
float far = 3*near; |
|
195 |
mDepth = (int)near; |
|
196 |
|
|
197 |
Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
198 |
} |
|
199 |
} |
|
200 |
} |
|
201 |
|
|
202 | 135 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
203 | 136 |
// if new size fits into the size of the underlying Texture, just change the projection without |
204 | 137 |
// reallocating the Texture. Otherwise, we need to reallocate. |
... | ... | |
207 | 140 |
|
208 | 141 |
void resizeFast(int width, int height) |
209 | 142 |
{ |
210 |
if( mWidth!=width || mHeight!=height )
|
|
143 |
if( mProjection.resize(width,height) )
|
|
211 | 144 |
{ |
212 |
mWidth = width; |
|
213 |
mHeight= height; |
|
214 |
|
|
215 |
createProjection(); |
|
216 |
|
|
217 |
if( mWidth> mSizeX || mHeight> mSizeY) |
|
145 |
if( width> mSizeX || height> mSizeY) |
|
218 | 146 |
{ |
219 |
mSizeX = mWidth;
|
|
220 |
mSizeY = mHeight;
|
|
147 |
mSizeX = width;
|
|
148 |
mSizeY = height;
|
|
221 | 149 |
delete(); |
222 | 150 |
} |
223 | 151 |
} |
... | ... | |
240 | 168 |
{ |
241 | 169 |
super(width,height,NOT_CREATED_YET); |
242 | 170 |
|
243 |
mProjectionMatrix = new float[16]; |
|
244 |
|
|
245 |
mHeight = height; |
|
246 |
mWidth = width; |
|
247 |
mFOV = 60.0f; |
|
248 |
mX = 0.0f; |
|
249 |
mY = 0.0f; |
|
171 |
mProjection = new DistortedProjection(width,height); |
|
250 | 172 |
mDepthEnabled= depthEnabled; |
251 | 173 |
mFBOH[0] = NOT_CREATED_YET; |
252 | 174 |
mDepthH[0] = NOT_CREATED_YET; |
253 |
|
|
254 |
createProjection(); |
|
255 | 175 |
} |
256 | 176 |
|
257 | 177 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
267 | 187 |
{ |
268 | 188 |
super(width,height,NOT_CREATED_YET); |
269 | 189 |
|
270 |
mProjectionMatrix = new float[16]; |
|
271 |
|
|
272 |
mHeight = height; |
|
273 |
mWidth = width; |
|
274 |
mFOV = 60.0f; |
|
275 |
mX = 0.0f; |
|
276 |
mY = 0.0f; |
|
190 |
mProjection = new DistortedProjection(width,height); |
|
277 | 191 |
mDepthEnabled= false; |
278 | 192 |
mFBOH[0] = NOT_CREATED_YET; |
279 | 193 |
mDepthH[0] = NOT_CREATED_YET; |
280 |
|
|
281 |
createProjection(); |
|
282 | 194 |
} |
283 | 195 |
|
284 | 196 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
285 | 197 |
/** |
286 |
* Create a new Framebuffer from an already created OpenGL Framebuffer. |
|
287 |
* <p> |
|
288 |
* Has to be followed by a 'resize()' to set the size. |
|
289 |
* |
|
290 |
* @param fbo the ID of a OpenGL Framebuffer object. Typically 0 (the screen) |
|
198 |
* Bind the underlying rectangle of pixels as a OpenGL Texture. |
|
291 | 199 |
*/ |
292 |
public DistortedFramebuffer(int fbo)
|
|
200 |
public boolean setAsInput()
|
|
293 | 201 |
{ |
294 |
super(0,0,DONT_CREATE); |
|
202 |
if( mColorH[0]>0 ) |
|
203 |
{ |
|
204 |
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]); |
|
205 |
return true; |
|
206 |
} |
|
207 |
|
|
208 |
return false; |
|
209 |
} |
|
295 | 210 |
|
296 |
mProjectionMatrix = new float[16]; |
|
211 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
212 |
/** |
|
213 |
* Bind this Surface as a Framebuffer we can render to. |
|
214 |
*/ |
|
215 |
public void setAsOutput() |
|
216 |
{ |
|
217 |
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]); |
|
297 | 218 |
|
298 |
mFOV = 60.0f; |
|
299 |
mX = 0.0f; |
|
300 |
mY = 0.0f; |
|
301 |
mDepthEnabled= true; |
|
302 |
mFBOH[0] = fbo; |
|
303 |
mDepthH[0] = DONT_CREATE; |
|
219 |
if( mDepthH[0]!=NOT_CREATED_YET ) |
|
220 |
{ |
|
221 |
GLES30.glEnable(GLES30.GL_DEPTH_TEST); |
|
222 |
GLES30.glDepthMask(true); |
|
223 |
} |
|
224 |
else |
|
225 |
{ |
|
226 |
GLES30.glDisable(GLES30.GL_DEPTH_TEST); |
|
227 |
GLES30.glDepthMask(false); |
|
228 |
} |
|
304 | 229 |
} |
305 | 230 |
|
306 | 231 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
322 | 247 |
* <p> |
323 | 248 |
* Must be called from a thread holding OpenGL Context. |
324 | 249 |
* |
325 |
* @param ren input Renderable to use.
|
|
250 |
* @param surface InputSurface to skin our Mesh with.
|
|
326 | 251 |
* @param mesh Class descendant from MeshObject |
327 | 252 |
* @param effects The DistortedEffects to use when rendering |
328 | 253 |
* @param time Current time, in milliseconds. |
329 | 254 |
*/ |
330 |
public void renderTo(DistortedRenderable ren, MeshObject mesh, DistortedEffects effects, long time)
|
|
255 |
public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time)
|
|
331 | 256 |
{ |
332 |
ren.create(); // Watch out - this needs to be before
|
|
333 |
create(); // the 'setAsInput' because this has side-effects! |
|
257 |
surface.create(); // Watch out - this needs to be before
|
|
258 |
create(); // the 'setAsInput' because this has side-effects!
|
|
334 | 259 |
|
335 |
if( ren.setAsInput() )
|
|
260 |
if( surface.setAsInput() )
|
|
336 | 261 |
{ |
337 | 262 |
DistortedRenderable.deleteAllMarked(); |
338 |
effects.drawPriv(ren.getWidth()/2.0f, ren.getHeight()/2.0f, mesh, this, time);
|
|
263 |
effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time);
|
|
339 | 264 |
} |
340 | 265 |
} |
341 | 266 |
|
... | ... | |
365 | 290 |
*/ |
366 | 291 |
public void setProjection(float fov, float x, float y) |
367 | 292 |
{ |
368 |
mFOV = fov; |
|
369 |
mX = x; |
|
370 |
mY = y; |
|
371 |
|
|
372 |
createProjection(); |
|
293 |
mProjection.set(fov,x,y); |
|
294 |
mProjection.createProjection(); |
|
373 | 295 |
} |
374 | 296 |
|
375 | 297 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
376 | 298 |
/** |
377 | 299 |
* Resize the underlying Framebuffer. |
378 | 300 |
* |
379 |
* As the Framebuffer is not created until the first render, typical usage of this API is actually |
|
380 |
* to set the size of an not-yet-created Framebuffer of an object that has been created with the |
|
381 |
* second constructor. |
|
382 |
* <p> |
|
383 |
* Fully creating an object, rendering to it, then resizing mid-render is also possible. Actual |
|
384 |
* resize takes place on the next render. |
|
385 |
* |
|
386 | 301 |
* @param width The new width. |
387 | 302 |
* @param height The new height. |
388 | 303 |
*/ |
389 | 304 |
public void resize(int width, int height) |
390 | 305 |
{ |
391 |
if( mWidth!=width || mHeight!=height )
|
|
306 |
if( mProjection.resize(width,height) )
|
|
392 | 307 |
{ |
393 |
mWidth = width; |
|
394 |
mHeight= height; |
|
395 | 308 |
mSizeX = width; |
396 | 309 |
mSizeY = height; |
397 |
|
|
398 |
createProjection(); |
|
399 |
|
|
400 | 310 |
if( mColorH[0]>0 ) markForDeletion(); |
401 | 311 |
} |
402 | 312 |
} |
... | ... | |
427 | 337 |
{ |
428 | 338 |
return mDepthEnabled; |
429 | 339 |
} |
340 |
|
|
341 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|
342 |
/** |
|
343 |
* Return Projection stored in this Framebuffer. |
|
344 |
* |
|
345 |
* @return DistortedProjection object. |
|
346 |
*/ |
|
347 |
public DistortedProjection getProjection() |
|
348 |
{ |
|
349 |
return mProjection; |
|
350 |
} |
|
430 | 351 |
} |
src/main/java/org/distorted/library/DistortedInputSurface.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2016 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
7 |
// it under the terms of the GNU General Public License as published by // |
|
8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
9 |
// (at your option) any later version. // |
|
10 |
// // |
|
11 |
// Distorted is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
14 |
// GNU General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU General Public License // |
|
17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19 |
|
|
20 |
package org.distorted.library; |
|
21 |
|
|
22 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
23 |
|
|
24 |
/** |
|
25 |
* A Surface that we can set as Input, i.e. take its rectangle of pixels and skin our Mesh with it. |
|
26 |
*/ |
|
27 |
|
|
28 |
public interface DistortedInputSurface extends DistortedSurface |
|
29 |
{ |
|
30 |
/** |
|
31 |
* Take the underlying rectangle of pixels and bind this texture to OpenGL. |
|
32 |
*/ |
|
33 |
boolean setAsInput(); |
|
34 |
} |
src/main/java/org/distorted/library/DistortedOutputSurface.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2016 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
7 |
// it under the terms of the GNU General Public License as published by // |
|
8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
9 |
// (at your option) any later version. // |
|
10 |
// // |
|
11 |
// Distorted is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
14 |
// GNU General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU General Public License // |
|
17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19 |
|
|
20 |
package org.distorted.library; |
|
21 |
|
|
22 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
23 |
|
|
24 |
/** |
|
25 |
* A Surface that we can set as Output, i.e. render to it. |
|
26 |
*/ |
|
27 |
|
|
28 |
public interface DistortedOutputSurface extends DistortedSurface |
|
29 |
{ |
|
30 |
/** |
|
31 |
* Bind this Surface as a Framebuffer we can render to. |
|
32 |
*/ |
|
33 |
void setAsOutput(); |
|
34 |
/** |
|
35 |
* Return the Projection. |
|
36 |
*/ |
|
37 |
DistortedProjection getProjection(); |
|
38 |
} |
src/main/java/org/distorted/library/DistortedProjection.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2016 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
7 |
// it under the terms of the GNU General Public License as published by // |
|
8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
9 |
// (at your option) any later version. // |
|
10 |
// // |
|
11 |
// Distorted is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
14 |
// GNU General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU General Public License // |
|
17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19 |
|
|
20 |
package org.distorted.library; |
|
21 |
|
|
22 |
import android.opengl.Matrix; |
|
23 |
|
|
24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
25 |
|
|
26 |
class DistortedProjection |
|
27 |
{ |
|
28 |
private float mX, mY, mFOV; |
|
29 |
int mWidth,mHeight,mDepth; |
|
30 |
float mDistance; |
|
31 |
float[] mProjectionMatrix; |
|
32 |
|
|
33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 |
|
|
35 |
DistortedProjection() |
|
36 |
{ |
|
37 |
mProjectionMatrix = new float[16]; |
|
38 |
|
|
39 |
mWidth = 0; |
|
40 |
mHeight= 0; |
|
41 |
|
|
42 |
mFOV = 60.0f; |
|
43 |
mX = 0.0f; |
|
44 |
mY = 0.0f; |
|
45 |
} |
|
46 |
|
|
47 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
48 |
|
|
49 |
DistortedProjection(int width, int height) |
|
50 |
{ |
|
51 |
mProjectionMatrix = new float[16]; |
|
52 |
|
|
53 |
mWidth = width; |
|
54 |
mHeight= height; |
|
55 |
|
|
56 |
mFOV = 60.0f; |
|
57 |
mX = 0.0f; |
|
58 |
mY = 0.0f; |
|
59 |
|
|
60 |
createProjection(); |
|
61 |
} |
|
62 |
|
|
63 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
64 |
|
|
65 |
boolean resize(int width, int height) |
|
66 |
{ |
|
67 |
if( mWidth!=width || mHeight!=height ) |
|
68 |
{ |
|
69 |
mWidth = width; |
|
70 |
mHeight= height; |
|
71 |
createProjection(); |
|
72 |
return true; |
|
73 |
} |
|
74 |
|
|
75 |
return false; |
|
76 |
} |
|
77 |
|
|
78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
79 |
|
|
80 |
void set(float fov, float x, float y) |
|
81 |
{ |
|
82 |
mFOV = fov; |
|
83 |
mX = x; |
|
84 |
mY = y; |
|
85 |
} |
|
86 |
|
|
87 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
88 |
|
|
89 |
void createProjection() |
|
90 |
{ |
|
91 |
if( mWidth>0 && mHeight>1 ) |
|
92 |
{ |
|
93 |
if( mFOV>0.0f ) // perspective projection |
|
94 |
{ |
|
95 |
float left = (-mX-mWidth /2.0f)/mHeight; |
|
96 |
float right = (-mX+mWidth /2.0f)/mHeight; |
|
97 |
float bottom = (-mY-mHeight/2.0f)/mHeight; |
|
98 |
float top = (-mY+mHeight/2.0f)/mHeight; |
|
99 |
float near = (top-bottom) / (2.0f*(float)Math.tan(mFOV*Math.PI/360)); |
|
100 |
mDistance = mHeight*near/(top-bottom); |
|
101 |
float far = 2*mDistance-near; |
|
102 |
mDepth = (int)((far-near)/2); |
|
103 |
|
|
104 |
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
105 |
} |
|
106 |
else // parallel projection |
|
107 |
{ |
|
108 |
float left = -mX-mWidth /2.0f; |
|
109 |
float right = -mX+mWidth /2.0f; |
|
110 |
float bottom = -mY-mHeight/2.0f; |
|
111 |
float top = -mY+mHeight/2.0f; |
|
112 |
float near = (mWidth+mHeight)/2; |
|
113 |
mDistance = 2*near; |
|
114 |
float far = 3*near; |
|
115 |
mDepth = (int)near; |
|
116 |
|
|
117 |
Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
118 |
} |
|
119 |
} |
|
120 |
} |
|
121 |
|
|
122 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
123 |
|
|
124 |
} |
src/main/java/org/distorted/library/DistortedRenderable.java | ||
---|---|---|
19 | 19 |
|
20 | 20 |
package org.distorted.library; |
21 | 21 |
|
22 |
import android.opengl.GLES30; |
|
23 |
|
|
24 | 22 |
import java.util.Iterator; |
25 | 23 |
import java.util.LinkedList; |
26 | 24 |
|
27 | 25 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
28 | 26 |
/** |
29 |
* Abstract class which represents a Renderable Object, i.e. something that we can take an skin our Mesh with. |
|
30 |
* <p> |
|
31 |
* Currently a DistortedTexture or a DistortedFramebuffer are Renderables. |
|
32 |
*/ |
|
33 |
public abstract class DistortedRenderable |
|
27 |
* Keep all objects created in a static LinkedList. The point: we need to be able to mark |
|
28 |
* Objects for deletion, and delete all marked Objects later at a convenient time (that's |
|
29 |
* because we can only delete from a thread that holds the OpenGL context so here we provide a |
|
30 |
* framework where one is able to mark for deletion at any time and actual deletion takes place |
|
31 |
* on the next render). |
|
32 |
*/ |
|
33 |
abstract class DistortedRenderable implements DistortedSurface |
|
34 | 34 |
{ |
35 | 35 |
static final int FAILED_TO_CREATE = -1; |
36 | 36 |
static final int NOT_CREATED_YET = -2; |
... | ... | |
45 | 45 |
|
46 | 46 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
47 | 47 |
|
48 |
abstract void create(); |
|
48 |
public abstract void create();
|
|
49 | 49 |
abstract void delete(); |
50 | 50 |
abstract void destroy(); |
51 | 51 |
|
... | ... | |
75 | 75 |
} |
76 | 76 |
} |
77 | 77 |
|
78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
79 |
|
|
80 |
long getID() |
|
81 |
{ |
|
82 |
return mColorH[0]; |
|
83 |
} |
|
84 |
|
|
85 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
86 |
|
|
87 |
boolean setAsInput() |
|
88 |
{ |
|
89 |
if( mColorH[0]>0 ) |
|
90 |
{ |
|
91 |
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]); |
|
92 |
return true; |
|
93 |
} |
|
94 |
|
|
95 |
return false; |
|
96 |
} |
|
97 |
|
|
98 | 78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
99 | 79 |
|
100 | 80 |
static synchronized void onDestroy() |
... | ... | |
131 | 111 |
mMarked = true; |
132 | 112 |
} |
133 | 113 |
|
114 |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
115 |
/** |
|
116 |
* Return unique ID of the Renderable. |
|
117 |
*/ |
|
118 |
public long getID() |
|
119 |
{ |
|
120 |
return mColorH[0]; |
|
121 |
} |
|
122 |
|
|
134 | 123 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
135 | 124 |
|
136 | 125 |
/** |
src/main/java/org/distorted/library/DistortedScreen.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2016 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
7 |
// it under the terms of the GNU General Public License as published by // |
|
8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
9 |
// (at your option) any later version. // |
|
10 |
// // |
|
11 |
// Distorted is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
14 |
// GNU General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU General Public License // |
|
17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19 |
|
|
20 |
package org.distorted.library; |
|
21 |
|
|
22 |
import android.opengl.GLES30; |
|
23 |
|
|
24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
25 |
/** |
|
26 |
* Class which represents the Screen. |
|
27 |
* <p> |
|
28 |
* User is able to render to it just like to a DistortedFramebuffer. |
|
29 |
*/ |
|
30 |
public class DistortedScreen extends DistortedRenderable implements DistortedOutputSurface |
|
31 |
{ |
|
32 |
private int[] mFBOH = new int[1]; |
|
33 |
private DistortedProjection mProjection; |
|
34 |
|
|
35 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
36 |
|
|
37 |
public void create() {} |
|
38 |
void delete() {} |
|
39 |
void destroy() {} |
|
40 |
|
|
41 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
42 |
// PUBLIC API |
|
43 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
44 |
/** |
|
45 |
* Create a new Screen. |
|
46 |
* <p> |
|
47 |
* Has to be followed by a 'resize()' to set the size. |
|
48 |
*/ |
|
49 |
public DistortedScreen() |
|
50 |
{ |
|
51 |
super(0,0,DONT_CREATE); |
|
52 |
|
|
53 |
mProjection = new DistortedProjection(); |
|
54 |
mFBOH[0] = 0; |
|
55 |
} |
|
56 |
|
|
57 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
58 |
/** |
|
59 |
* Bind this Surface as a Framebuffer we can render to. |
|
60 |
*/ |
|
61 |
public void setAsOutput() |
|
62 |
{ |
|
63 |
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]); |
|
64 |
GLES30.glEnable(GLES30.GL_DEPTH_TEST); |
|
65 |
GLES30.glDepthMask(true); |
|
66 |
} |
|
67 |
|
|
68 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
69 |
|
|
70 |
/** |
|
71 |
* Draw the (texture,mesh,effects) object to the Framebuffer. |
|
72 |
* <p> |
|
73 |
* Must be called from a thread holding OpenGL Context. |
|
74 |
* |
|
75 |
* @param surface InputSurface to skin our Mesh with. |
|
76 |
* @param mesh Class descendant from MeshObject |
|
77 |
* @param effects The DistortedEffects to use when rendering |
|
78 |
* @param time Current time, in milliseconds. |
|
79 |
*/ |
|
80 |
public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time) |
|
81 |
{ |
|
82 |
surface.create(); // Watch out - this needs to be before |
|
83 |
create(); // the 'setAsInput' because this has side-effects! |
|
84 |
|
|
85 |
if( surface.setAsInput() ) |
|
86 |
{ |
|
87 |
DistortedRenderable.deleteAllMarked(); |
|
88 |
effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time); |
|
89 |
} |
|
90 |
} |
|
91 |
|
|
92 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
93 |
/** |
|
94 |
* Draws the Tree, and all its children, to the Framebuffer. |
|
95 |
* <p> |
|
96 |
* Must be called from a thread holding OpenGL Context. |
|
97 |
* |
|
98 |
* @param dt DistortedTree to render. |
|
99 |
* @param time Current time, in milliseconds. This will be passed to all the Effects stored in the Tree. |
|
100 |
*/ |
|
101 |
public void renderTo(DistortedTree dt, long time) |
|
102 |
{ |
|
103 |
DistortedRenderable.deleteAllMarked(); |
|
104 |
create(); |
|
105 |
dt.drawRecursive(time,this); |
|
106 |
} |
|
107 |
|
|
108 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
109 |
/** |
|
110 |
* Create new Projection matrix. |
|
111 |
* |
|
112 |
* @param fov Vertical 'field of view' of the Projection frustrum (in degrees). |
|
113 |
* @param x X-coordinate of the point at which our camera looks at. 0 is the center. |
|
114 |
* @param y Y-coordinate of the point at which our camera looks at. 0 is the center. |
|
115 |
*/ |
|
116 |
public void setProjection(float fov, float x, float y) |
|
117 |
{ |
|
118 |
mProjection.set(fov,x,y); |
|
119 |
mProjection.createProjection(); |
|
120 |
} |
|
121 |
|
|
122 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
123 |
/** |
|
124 |
* Resize the underlying Projection. |
|
125 |
* |
|
126 |
* @param width The new width. |
|
127 |
* @param height The new height. |
|
128 |
*/ |
|
129 |
public void resize(int width, int height) |
|
130 |
{ |
|
131 |
if( mProjection.resize(width,height) ) |
|
132 |
{ |
|
133 |
mSizeX = width; |
|
134 |
mSizeY = height; |
|
135 |
} |
|
136 |
} |
|
137 |
|
|
138 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|
139 |
/** |
|
140 |
* Return Projection stored in this Framebuffer. |
|
141 |
* |
|
142 |
* @return DistortedProjection object. |
|
143 |
*/ |
|
144 |
public DistortedProjection getProjection() |
|
145 |
{ |
|
146 |
return mProjection; |
|
147 |
} |
|
148 |
} |
src/main/java/org/distorted/library/DistortedSurface.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2016 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
7 |
// it under the terms of the GNU General Public License as published by // |
|
8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
9 |
// (at your option) any later version. // |
|
10 |
// // |
|
11 |
// Distorted is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
14 |
// GNU General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU General Public License // |
|
17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19 |
|
|
20 |
package org.distorted.library; |
|
21 |
|
|
22 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
23 |
|
|
24 |
/** |
|
25 |
* Abstract Surface. |
|
26 |
*/ |
|
27 |
|
|
28 |
interface DistortedSurface |
|
29 |
{ |
|
30 |
/** |
|
31 |
* Create the underlying OpenGL part of the Surface. |
|
32 |
*/ |
|
33 |
void create(); |
|
34 |
/** |
|
35 |
* Return a unique ID of this Surface. |
|
36 |
*/ |
|
37 |
long getID(); |
|
38 |
/** |
|
39 |
* Return the width of this Surface. |
|
40 |
*/ |
|
41 |
int getWidth(); |
|
42 |
/** |
|
43 |
* Return the height of this Surface. |
|
44 |
*/ |
|
45 |
int getHeight(); |
|
46 |
} |
src/main/java/org/distorted/library/DistortedTexture.java | ||
---|---|---|
29 | 29 |
* Class which represents a OpenGL Texture object. |
30 | 30 |
* <p> |
31 | 31 |
* Create a Texture of arbitrary size and feed some pixels to it via the setTexture() method. |
32 |
* <p> |
|
33 |
* Keep all objects created in a static LinkedList. The point: we need to be able to mark |
|
34 |
* Textures for deletion, and delete all marked objects later at a convenient time (that's |
|
35 |
* because we can only delete from a thread that holds the OpenGL context so here we provide a |
|
36 |
* framework where one is able to mark for deletion at any time and actual deletion takes place |
|
37 |
* on the next render). |
|
38 | 32 |
*/ |
39 |
public class DistortedTexture extends DistortedRenderable |
|
33 |
public class DistortedTexture extends DistortedRenderable implements DistortedInputSurface
|
|
40 | 34 |
{ |
41 | 35 |
private Bitmap mBmp= null; |
42 | 36 |
|
... | ... | |
61 | 55 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
62 | 56 |
// must be called from a thread holding OpenGL Context |
63 | 57 |
|
64 |
void create() |
|
58 |
public void create()
|
|
65 | 59 |
{ |
66 | 60 |
if( mBmp!=null && mColorH !=null ) |
67 | 61 |
{ |
... | ... | |
104 | 98 |
{ |
105 | 99 |
if( mColorH[0]!=DONT_CREATE ) mColorH[0] = NOT_CREATED_YET; |
106 | 100 |
} |
101 |
|
|
107 | 102 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
108 | 103 |
|
109 | 104 |
static void getUniforms(int mProgramH) |
... | ... | |
126 | 121 |
mBmp= null; |
127 | 122 |
} |
128 | 123 |
|
124 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
125 |
/** |
|
126 |
* Bind the underlying rectangle of pixels as a OpenGL Texture. |
|
127 |
*/ |
|
128 |
public boolean setAsInput() |
|
129 |
{ |
|
130 |
if( mColorH[0]>0 ) |
|
131 |
{ |
|
132 |
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]); |
|
133 |
return true; |
|
134 |
} |
|
135 |
|
|
136 |
return false; |
|
137 |
} |
|
138 |
|
|
129 | 139 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
130 | 140 |
/** |
131 | 141 |
* Sets the underlying android.graphics.Bitmap object. |
src/main/java/org/distorted/library/DistortedTree.java | ||
---|---|---|
38 | 38 |
|
39 | 39 |
private MeshObject mMesh; |
40 | 40 |
private DistortedEffects mEffects; |
41 |
private DistortedRenderable mRenderable;
|
|
41 |
private DistortedInputSurface mSurface;
|
|
42 | 42 |
private NodeData mData; |
43 | 43 |
|
44 | 44 |
private DistortedTree mParent; |
... | ... | |
94 | 94 |
{ |
95 | 95 |
ArrayList<Long> ret = new ArrayList<>(); |
96 | 96 |
|
97 |
ret.add( mRenderable.getID() );
|
|
97 |
ret.add( mSurface.getID() );
|
|
98 | 98 |
DistortedTree node; |
99 | 99 |
|
100 | 100 |
for(int i=0; i<mNumChildren[0]; i++) |
... | ... | |
125 | 125 |
if( newList.size()>1 ) |
126 | 126 |
{ |
127 | 127 |
if( mData.mFBO ==null ) |
128 |
mData.mFBO = new DistortedFramebuffer(mRenderable.getWidth(), mRenderable.getHeight());
|
|
128 |
mData.mFBO = new DistortedFramebuffer(mSurface.getWidth(), mSurface.getHeight());
|
|
129 | 129 |
} |
130 | 130 |
else |
131 | 131 |
{ |
... | ... | |
198 | 198 |
*/ |
199 | 199 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
200 | 200 |
|
201 |
void drawRecursive(long currTime, DistortedFramebuffer df)
|
|
201 |
void drawRecursive(long currTime, DistortedOutputSurface surface)
|
|
202 | 202 |
{ |
203 |
mRenderable.create();
|
|
204 |
float halfX = mRenderable.getWidth()/2.0f;
|
|
205 |
float halfY = mRenderable.getHeight()/2.0f;
|
|
203 |
mSurface.create();
|
|
204 |
float halfX = mSurface.getWidth()/2.0f;
|
|
205 |
float halfY = mSurface.getHeight()/2.0f;
|
|
206 | 206 |
|
207 | 207 |
if( mNumChildren[0]<=0 ) |
208 | 208 |
{ |
209 |
mRenderable.setAsInput();
|
|
209 |
mSurface.setAsInput();
|
|
210 | 210 |
} |
211 | 211 |
else |
212 | 212 |
{ |
... | ... | |
219 | 219 |
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
220 | 220 |
GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT); |
221 | 221 |
|
222 |
if( mRenderable.setAsInput() )
|
|
223 |
DistortedEffects.drawNoEffectsPriv(halfX, halfY, mMesh, mData.mFBO); |
|
222 |
if( mSurface.setAsInput() )
|
|
223 |
DistortedEffects.drawNoEffectsPriv(halfX, halfY, mMesh, mData.mFBO.getProjection() );
|
|
224 | 224 |
|
225 | 225 |
synchronized(this) |
226 | 226 |
{ |
... | ... | |
236 | 236 |
mData.mFBO.setAsInput(); |
237 | 237 |
} |
238 | 238 |
|
239 |
mEffects.drawPriv(halfX, halfY, mMesh, df, currTime);
|
|
239 |
mEffects.drawPriv(halfX, halfY, mMesh, surface, currTime);
|
|
240 | 240 |
} |
241 | 241 |
|
242 | 242 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
245 | 245 |
/** |
246 | 246 |
* Constructs new Node of the Tree. |
247 | 247 |
* |
248 |
* @param renderable DistortedRenderable to put into the new Node.
|
|
248 |
* @param surface InputSurface to put into the new Node.
|
|
249 | 249 |
* @param effects DistortedEffects to put into the new Node. |
250 | 250 |
* @param mesh MeshObject to put into the new Node. |
251 | 251 |
*/ |
252 |
public DistortedTree(DistortedRenderable renderable, DistortedEffects effects, MeshObject mesh)
|
|
252 |
public DistortedTree(DistortedInputSurface surface, DistortedEffects effects, MeshObject mesh)
|
|
253 | 253 |
{ |
254 |
mRenderable = renderable;
|
|
254 |
mSurface = surface;
|
|
255 | 255 |
mEffects = effects; |
256 | 256 |
mMesh = mesh; |
257 | 257 |
mParent = null; |
... | ... | |
260 | 260 |
mNumChildren[0]= 0; |
261 | 261 |
|
262 | 262 |
ArrayList<Long> list = new ArrayList<>(); |
263 |
list.add(mRenderable.getID());
|
|
263 |
list.add(mSurface.getID());
|
|
264 | 264 |
|
265 | 265 |
mData = mMapNodeID.get(list); |
266 | 266 |
|
... | ... | |
293 | 293 |
|
294 | 294 |
if( (flags & Distorted.CLONE_RENDERABLE) != 0 ) |
295 | 295 |
{ |
296 |
mRenderable = node.mRenderable;
|
|
296 |
mSurface = node.mSurface;
|
|
297 | 297 |
} |
298 | 298 |
else |
299 | 299 |
{ |
300 |
int w = node.mRenderable.getWidth();
|
|
301 |
int h = node.mRenderable.getHeight();
|
|
300 |
int w = node.mSurface.getWidth();
|
|
301 |
int h = node.mSurface.getHeight();
|
|
302 | 302 |
|
303 |
if( node.mRenderable instanceof DistortedTexture )
|
|
303 |
if( node.mSurface instanceof DistortedTexture )
|
|
304 | 304 |
{ |
305 |
mRenderable = new DistortedTexture(w,h);
|
|
305 |
mSurface = new DistortedTexture(w,h);
|
|
306 | 306 |
} |
307 |
else if( node.mRenderable instanceof DistortedFramebuffer )
|
|
307 |
else if( node.mSurface instanceof DistortedFramebuffer )
|
|
308 | 308 |
{ |
309 |
boolean hasDepth = ((DistortedFramebuffer) node.mRenderable).hasDepth();
|
|
310 |
mRenderable = new DistortedFramebuffer(w,h,hasDepth);
|
|
309 |
boolean hasDepth = ((DistortedFramebuffer) node.mSurface).hasDepth();
|
|
310 |
mSurface = new DistortedFramebuffer(w,h,hasDepth);
|
|
311 | 311 |
} |
312 | 312 |
} |
313 | 313 |
if( (flags & Distorted.CLONE_CHILDREN) != 0 ) |
... | ... | |
360 | 360 |
/** |
361 | 361 |
* Adds a new child to the last position in the list of our Node's children. |
362 | 362 |
* |
363 |
* @param renderable DistortedRenderable to initialize our child Node with.
|
|
363 |
* @param surface InputSurface to initialize our child Node with.
|
|
364 | 364 |
* @param effects DistortedEffects to initialize our child Node with. |
365 | 365 |
* @param mesh MeshObject to initialize our child Node with. |
366 | 366 |
* @return the newly constructed child Node, or null if we couldn't allocate resources. |
367 | 367 |
*/ |
368 |
public synchronized DistortedTree attach(DistortedRenderable renderable, DistortedEffects effects, MeshObject mesh)
|
|
368 |
public synchronized DistortedTree attach(DistortedInputSurface surface, DistortedEffects effects, MeshObject mesh)
|
|
369 | 369 |
{ |
370 | 370 |
ArrayList<Long> prev = generateIDList(); |
371 | 371 |
|
372 | 372 |
if( mChildren==null ) mChildren = new ArrayList<>(2); |
373 |
DistortedTree node = new DistortedTree(renderable,effects,mesh);
|
|
373 |
DistortedTree node = new DistortedTree(surface,effects,mesh);
|
|
374 | 374 |
node.mParent = this; |
375 | 375 |
mChildren.add(node); |
376 | 376 |
mNumChildren[0]++; |
... | ... | |
474 | 474 |
|
475 | 475 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
476 | 476 |
/** |
477 |
* Returns the DistortedRenderable object that's in the Node.
|
|
477 |
* Returns the DistortedInputSurface object that's in the Node.
|
|
478 | 478 |
* |
479 |
* @return The DistortedRenderable contained in the Node.
|
|
479 |
* @return The DistortedInputSurface contained in the Node.
|
|
480 | 480 |
*/ |
481 |
public DistortedRenderable getRenderable()
|
|
481 |
public DistortedInputSurface getSurface()
|
|
482 | 482 |
{ |
483 |
return mRenderable;
|
|
483 |
return mSurface;
|
|
484 | 484 |
} |
485 | 485 |
|
486 | 486 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/library/EffectQueueMatrix.java | ||
---|---|---|
107 | 107 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
108 | 108 |
// here construct the ModelView and the ModelViewProjection Matrices |
109 | 109 |
|
110 |
void constructMatrices(DistortedFramebuffer df, float halfX, float halfY)
|
|
110 |
void constructMatrices(DistortedProjection projection, float halfX, float halfY)
|
|
111 | 111 |
{ |
112 | 112 |
Matrix.setIdentityM(mViewMatrix, 0); |
113 |
Matrix.translateM(mViewMatrix, 0, -df.mWidth/2, df.mHeight/2, -df.mDistance);
|
|
113 |
Matrix.translateM(mViewMatrix, 0, -projection.mWidth/2, projection.mHeight/2, -projection.mDistance);
|
|
114 | 114 |
|
115 | 115 |
float x,y,z, sx,sy,sz; |
116 | 116 |
|
... | ... | |
184 | 184 |
} |
185 | 185 |
|
186 | 186 |
Matrix.translateM(mViewMatrix, 0, halfX,-halfY, 0); |
187 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mViewMatrix, 0);
|
|
187 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mViewMatrix, 0);
|
|
188 | 188 |
} |
189 | 189 |
|
190 | 190 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
284 | 284 |
|
285 | 285 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
286 | 286 |
|
287 |
synchronized void send(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
|
|
287 |
synchronized void send(DistortedProjection projection, float halfX, float halfY, float halfZ)
|
|
288 | 288 |
{ |
289 |
constructMatrices(df,halfX,halfY);
|
|
289 |
constructMatrices(projection,halfX,halfY);
|
|
290 | 290 |
|
291 | 291 |
GLES30.glUniform3f( mObjDH , halfX, halfY, halfZ); |
292 |
GLES30.glUniform1f( mDepthH, df.mDepth);
|
|
292 |
GLES30.glUniform1f( mDepthH, projection.mDepth);
|
|
293 | 293 |
GLES30.glUniformMatrix4fv(mMVMatrixH , 1, false, mViewMatrix, 0); |
294 | 294 |
GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0); |
295 | 295 |
} |
... | ... | |
297 | 297 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
298 | 298 |
// here construct the ModelView Matrix, but without any effects |
299 | 299 |
|
300 |
synchronized static void sendZero(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
|
|
300 |
synchronized static void sendZero(DistortedProjection projection, float halfX, float halfY, float halfZ)
|
|
301 | 301 |
{ |
302 | 302 |
Matrix.setIdentityM(mTmpMatrix, 0); |
303 |
Matrix.translateM(mTmpMatrix, 0, halfX-df.mWidth/2, df.mHeight/2-halfY, -df.mDistance);
|
|
304 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
303 |
Matrix.translateM(mTmpMatrix, 0, halfX-projection.mWidth/2, projection.mHeight/2-halfY, -projection.mDistance);
|
|
304 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
305 | 305 |
|
306 | 306 |
GLES30.glUniform3f( mObjDH , halfX, halfY, halfZ); |
307 |
GLES30.glUniform1f( mDepthH, df.mDepth);
|
|
307 |
GLES30.glUniform1f( mDepthH, projection.mDepth);
|
|
308 | 308 |
GLES30.glUniformMatrix4fv(mMVMatrixH , 1, false, mTmpMatrix, 0); |
309 | 309 |
GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix, 0); |
310 | 310 |
} |
src/main/java/org/distorted/library/EffectQueuePostprocess.java | ||
---|---|---|
229 | 229 |
// w,h - width and height of the input texture. MVP - Model-View-Projection matrix to apply to the |
230 | 230 |
// texture; df - output FBO. |
231 | 231 |
|
232 |
synchronized void render(float w, float h, float[] mvp, DistortedFramebuffer df)
|
|
232 |
synchronized void render(float w, float h, float[] mvp, DistortedOutputSurface surface)
|
|
233 | 233 |
{ |
234 | 234 |
mBlurProgram.useProgram(); |
235 | 235 |
|
236 |
DistortedProjection inputP = mBufferFBO.getProjection(); |
|
237 |
DistortedProjection outputP = surface.getProjection(); |
|
238 |
|
|
236 | 239 |
int radius = (int)mUniforms[0]; |
237 | 240 |
if( radius>=MAX_BLUR ) radius = MAX_BLUR-1; |
238 | 241 |
computeGaussianKernel(radius); |
... | ... | |
252 | 255 |
GLES30.glViewport(0, 0, (int)w, (int)h); |
253 | 256 |
|
254 | 257 |
Matrix.setIdentityM(mTmpMatrix, 0); |
255 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -mBufferFBO.mDistance);
|
|
256 |
Matrix.multiplyMM(mMVPMatrix, 0, mBufferFBO.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
258 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -inputP.mDistance);
|
|
259 |
Matrix.multiplyMM(mMVPMatrix, 0, inputP.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
257 | 260 |
|
258 | 261 |
// horizontal blur |
259 | 262 |
GLES30.glUniform1fv( mOffsetsH ,radius+1, mOffsets,0); |
... | ... | |
263 | 266 |
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4); |
264 | 267 |
|
265 | 268 |
mBufferFBO.setAsInput(); |
266 |
df.setAsOutput(); |
|
267 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight); |
|
269 |
surface.setAsOutput(); |
|
270 |
|
|
271 |
GLES30.glViewport(0, 0, outputP.mWidth, outputP.mHeight); |
|
268 | 272 |
|
269 | 273 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/w; |
270 | 274 |
|
Also available in: Unified diff
Major: change of API.
Split DFramebuffer into Framebuffer and Screen; introduce the 'DistortedInputSurface' and 'DistortedOutputSurface' interfaces.