Project

General

Profile

« Previous | Next » 

Revision c5369f1b

Added by Leszek Koltunski about 7 years ago

Major: change of API.

Split DFramebuffer into Framebuffer and Screen; introduce the 'DistortedInputSurface' and 'DistortedOutputSurface' interfaces.

View differences:

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
  }

Also available in: Unified diff