Project

General

Profile

Download (10.8 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / DistortedFramebuffer.java @ af27df87

1 f6fb3c6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 194ab46f Leszek Koltunski
import android.opengl.GLES30;
23 f6fb3c6d Leszek Koltunski
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25 dedacd82 Leszek Koltunski
/**
26
 * Class which represents a OpenGL Framebuffer object.
27 71c3fecc Leszek Koltunski
 * <p>
28 c5369f1b leszek
 * User is able to create offscreen FBOs and both a) render to them b) use their COLOR0 attachment as
29
 * an input texture.
30 dedacd82 Leszek Koltunski
 */
31 af4cc5db Leszek Koltunski
public class DistortedFramebuffer extends DistortedOutputSurface implements DistortedInputSurface
32 f6fb3c6d Leszek Koltunski
  {
33 133cbb2b Leszek Koltunski
  private int[] mDepthH = new int[1];
34
  private int[] mFBOH   = new int[1];
35 cdd5e827 Leszek Koltunski
  private boolean mDepthEnabled;
36 bd3da5b2 Leszek Koltunski
37 f6fb3c6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
38 6537ba91 Leszek Koltunski
// Must be called from a thread holding OpenGL Context
39 227ac49a Leszek Koltunski
// Watch out - this has the side-effect of binding a Texture and a Framebuffer!
40 f6fb3c6d Leszek Koltunski
41 f8377ef8 leszek
  void create()
42 f6fb3c6d Leszek Koltunski
    {
43 133cbb2b Leszek Koltunski
    if( mColorH[0]==NOT_CREATED_YET )
44 7cf783cb Leszek Koltunski
      {
45 133cbb2b Leszek Koltunski
      GLES30.glGenTextures(1, mColorH, 0);
46
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]);
47 194ab46f Leszek Koltunski
      GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
48
      GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
49
      GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
50
      GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
51 133cbb2b Leszek Koltunski
      GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, mSizeX, mSizeY, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);
52 194ab46f Leszek Koltunski
53 133cbb2b Leszek Koltunski
      GLES30.glGenFramebuffers(1, mFBOH, 0);
54
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]);
55
      GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, mColorH[0], 0);
56 dedacd82 Leszek Koltunski
57 8337fa41 Leszek Koltunski
      checkStatus("color");
58 7cf783cb Leszek Koltunski
      }
59 133cbb2b Leszek Koltunski
    if( mDepthEnabled && mDepthH[0]==NOT_CREATED_YET ) // we need to create a new DEPTH attachment
60 8c327653 Leszek Koltunski
      {
61 133cbb2b Leszek Koltunski
      GLES30.glGenTextures(1, mDepthH, 0);
62
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mDepthH[0]);
63 194ab46f Leszek Koltunski
      GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
64
      GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
65
      GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
66
      GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
67 133cbb2b Leszek Koltunski
      GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH_COMPONENT, mSizeX, mSizeY, 0, GLES30.GL_DEPTH_COMPONENT, GLES30.GL_UNSIGNED_SHORT, null);
68 8c327653 Leszek Koltunski
69 133cbb2b Leszek Koltunski
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]);
70
      GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthH[0], 0);
71 8c327653 Leszek Koltunski
72 8337fa41 Leszek Koltunski
      checkStatus("depth");
73 8c327653 Leszek Koltunski
      }
74 f8377ef8 leszek
    if( !mDepthEnabled && mDepthH[0]!=NOT_CREATED_YET ) // we need to detach and recreate the DEPTH attachment.
75 8c327653 Leszek Koltunski
      {
76 133cbb2b Leszek Koltunski
      GLES30.glDeleteTextures(1, mDepthH, 0);
77
      mDepthH[0]=NOT_CREATED_YET;
78 8c327653 Leszek Koltunski
      }
79 8337fa41 Leszek Koltunski
    }
80
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82
83
  private boolean checkStatus(String message)
84
    {
85 194ab46f Leszek Koltunski
    int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
86 8337fa41 Leszek Koltunski
87 194ab46f Leszek Koltunski
    if(status != GLES30.GL_FRAMEBUFFER_COMPLETE)
88 8337fa41 Leszek Koltunski
      {
89
      android.util.Log.e("DistortedFramebuffer", "FRAMEBUFFER INCOMPLETE, "+message+" error="+status);
90
91 133cbb2b Leszek Koltunski
      GLES30.glDeleteTextures(1, mColorH, 0);
92
      GLES30.glDeleteTextures(1, mDepthH, 0);
93
      GLES30.glDeleteFramebuffers(1, mFBOH, 0);
94
      mFBOH[0]   = 0;
95
      mColorH[0] = FAILED_TO_CREATE;
96
      mDepthH[0] = FAILED_TO_CREATE;
97 8337fa41 Leszek Koltunski
98
      return false;
99
      }
100 8c327653 Leszek Koltunski
101 f6fb3c6d Leszek Koltunski
    return true;
102
    }
103
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105 6537ba91 Leszek Koltunski
// Must be called from a thread holding OpenGL Context
106 f6fb3c6d Leszek Koltunski
107 227ac49a Leszek Koltunski
  void delete()
108 f6fb3c6d Leszek Koltunski
    {
109 133cbb2b Leszek Koltunski
    if( mColorH[0]>=0 )
110 e6cf7d50 Leszek Koltunski
      {
111 133cbb2b Leszek Koltunski
      if( mDepthH[0]>=0 )
112 8c327653 Leszek Koltunski
        {
113 133cbb2b Leszek Koltunski
        GLES30.glDeleteTextures(1, mDepthH, 0);
114
        mDepthH[0]=NOT_CREATED_YET;
115 8c327653 Leszek Koltunski
        }
116
117 133cbb2b Leszek Koltunski
      GLES30.glDeleteTextures(1, mColorH, 0);
118
      mColorH[0] = NOT_CREATED_YET;
119 bd3da5b2 Leszek Koltunski
120 133cbb2b Leszek Koltunski
      GLES30.glDeleteFramebuffers(1, mFBOH, 0);
121
      mFBOH[0] = 0;
122 e6cf7d50 Leszek Koltunski
      }
123 bd3da5b2 Leszek Koltunski
    }
124
125 4ebbb17a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
126
// called from onDestroy(); mark OpenGL assets as 'not created'
127
128 f8377ef8 leszek
  void recreate()
129 4ebbb17a Leszek Koltunski
    {
130
    if( mColorH[0]!=DONT_CREATE ) mColorH[0] = NOT_CREATED_YET;
131
    if( mDepthEnabled           ) mDepthH[0] = NOT_CREATED_YET;
132
    }
133
134 86eb00a9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
135
// if new size fits into the size of the underlying Texture, just change the projection without
136
// reallocating the Texture. Otherwise, we need to reallocate.
137
//
138 af4cc5db Leszek Koltunski
// Must be called from a thread holding the OpenGL context.
139 86eb00a9 Leszek Koltunski
140
  void resizeFast(int width, int height)
141
    {
142 af4cc5db Leszek Koltunski
    if( mWidth!=width || mHeight!=height )
143 86eb00a9 Leszek Koltunski
      {
144 af4cc5db Leszek Koltunski
      mWidth = width;
145
      mHeight= height;
146
      createProjection();
147
148 c5369f1b leszek
      if( width> mSizeX || height> mSizeY)
149 86eb00a9 Leszek Koltunski
        {
150 c5369f1b leszek
        mSizeX = width;
151
        mSizeY = height;
152 133cbb2b Leszek Koltunski
        delete();
153 86eb00a9 Leszek Koltunski
        }
154
      }
155 cc0734e7 Leszek Koltunski
156 133cbb2b Leszek Koltunski
    create();
157 86eb00a9 Leszek Koltunski
    }
158
159 af27df87 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
160
// create 'system' Framebuffers, i.e. those that are used internally by the library.
161
// Those do not get removed in onDestroy();
162
163
  public DistortedFramebuffer(boolean depthEnabled, int width, int height)
164
    {
165
    super(width,height,NOT_CREATED_YET,true);
166
    mDepthEnabled= depthEnabled;
167
    mFBOH[0]     = NOT_CREATED_YET;
168
    mDepthH[0]   = NOT_CREATED_YET;
169
    }
170
171 f6fb3c6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// PUBLIC API
173 dedacd82 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
174 cdd5e827 Leszek Koltunski
/**
175
 * Create a new offscreen Framebuffer.
176
 *
177
 * @param width Width of the COLOR attachment.
178
 * @param height Height of the COLOR attachment.
179
 * @param depthEnabled Add DEPTH attachment?
180
 */
181
  @SuppressWarnings("unused")
182
  public DistortedFramebuffer(int width, int height, boolean depthEnabled)
183
    {
184 af27df87 leszek
    super(width,height,NOT_CREATED_YET,false);
185 cdd5e827 Leszek Koltunski
    mDepthEnabled= depthEnabled;
186 2e49718d Leszek Koltunski
    mFBOH[0]     = NOT_CREATED_YET;
187
    mDepthH[0]   = NOT_CREATED_YET;
188 cdd5e827 Leszek Koltunski
    }
189
190 133cbb2b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
191
192 dedacd82 Leszek Koltunski
/**
193 57578636 Leszek Koltunski
 * Create a new offscreen Framebuffer.
194 dedacd82 Leszek Koltunski
 *
195
 * @param width Width of the COLOR attachment.
196
 * @param height Height of the COLOR attachment.
197
 */
198 1942537e Leszek Koltunski
  @SuppressWarnings("unused")
199 ed13a5de Leszek Koltunski
  public DistortedFramebuffer(int width, int height)
200 f6fb3c6d Leszek Koltunski
    {
201 af27df87 leszek
    super(width,height,NOT_CREATED_YET,false);
202 cdd5e827 Leszek Koltunski
    mDepthEnabled= false;
203 2e49718d Leszek Koltunski
    mFBOH[0]     = NOT_CREATED_YET;
204
    mDepthH[0]   = NOT_CREATED_YET;
205 f6fb3c6d Leszek Koltunski
    }
206
207 b448e6b9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
208 dedacd82 Leszek Koltunski
/**
209 c5369f1b leszek
 * Bind the underlying rectangle of pixels as a OpenGL Texture.
210 af4cc5db Leszek Koltunski
 *
211
 * @returns <code>true</code> if successful.
212 dedacd82 Leszek Koltunski
 */
213 c5369f1b leszek
  public boolean setAsInput()
214 b448e6b9 Leszek Koltunski
    {
215 c5369f1b leszek
    if( mColorH[0]>0 )
216
      {
217
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]);
218
      return true;
219
      }
220
221
    return false;
222
    }
223 2e49718d Leszek Koltunski
224 c5369f1b leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
225
/**
226
 * Bind this Surface as a Framebuffer we can render to.
227
 */
228
  public void setAsOutput()
229
    {
230
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]);
231 b448e6b9 Leszek Koltunski
232 c5369f1b leszek
    if( mDepthH[0]!=NOT_CREATED_YET )
233
      {
234
      GLES30.glEnable(GLES30.GL_DEPTH_TEST);
235
      GLES30.glDepthMask(true);
236
      }
237
    else
238
      {
239
      GLES30.glDisable(GLES30.GL_DEPTH_TEST);
240
      GLES30.glDepthMask(false);
241
      }
242 8c327653 Leszek Koltunski
    }
243
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
/**
246 f8377ef8 leszek
 * Create a new DEPTH buffer and attach it or (param=false) detach an existing DEPTh attachment and recreate it.
247 8c327653 Leszek Koltunski
 *
248 cdd5e827 Leszek Koltunski
 * @param enable <bold>true</bold> if we want to attach a new DEPTH buffer to the FBO.<br>
249
 *               <bold>false</bold> if we want to detach the DEPTH attachment.
250 8c327653 Leszek Koltunski
 */
251 cdd5e827 Leszek Koltunski
  public void enableDepthAttachment(boolean enable)
252 8c327653 Leszek Koltunski
    {
253 f8377ef8 leszek
    if( mDepthEnabled!=enable )
254
      {
255
      mDepthEnabled = enable;
256
      moveToToDo();
257
      }
258 b448e6b9 Leszek Koltunski
    }
259
260 d1e740c5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
261
/**
262 09d4f4b1 Leszek Koltunski
 * Return the ID of the Texture (COLOR attachment 0) that's backing this FBO.
263
 * <p>
264
 * Catch: this will only work if the library has had time to actually create the texture. Remember
265
 * that the texture gets created only on first render, thus creating a Texture object and immediately
266
 * calling this method will return an invalid (negative) result.
267
 *
268 ab12f06b Leszek Koltunski
 * @return If there was not a single render between creation of the Object and calling this method on
269
 *         it, return a negative value. Otherwise, return ID of COLOR attachment 0.
270 d1e740c5 Leszek Koltunski
 */
271 09d4f4b1 Leszek Koltunski
  public int getTextureID()
272 d1e740c5 Leszek Koltunski
    {
273 133cbb2b Leszek Koltunski
    return mColorH[0];
274 8c327653 Leszek Koltunski
    }
275
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277
/**
278
 * Return true if the FBO contains a DEPTH attachment.
279
 *
280
 * @return <bold>true</bold> if the FBO contains a DEPTH attachment.
281
 */
282
  public boolean hasDepth()
283
    {
284 cdd5e827 Leszek Koltunski
    return mDepthEnabled;
285 d1e740c5 Leszek Koltunski
    }
286 f6fb3c6d Leszek Koltunski
  }