Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedFramebuffer.java @ 16d8b8f3

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.GLES20;
23
import android.opengl.Matrix;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
public class DistortedFramebuffer
28
  {
29
  private static final int TEXTURE_FAILED_TO_CREATE = -1;
30
  private static final int TEXTURE_NOT_CREATED_YET  = -2;
31
  private static final int TEXTURE_DONT_CREATE      = -3;
32

    
33
  private int mFramebufferID, mTextureID;
34
  private float mX, mY;
35
  private float mFOV;
36

    
37
  int mWidth,mHeight,mDepth,mDistance;
38
  float[] mProjectionMatrix;
39
  boolean mMarked;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

    
43
  private void createProjection()
44
    {
45
    float ratio  = (float) mWidth / mHeight;
46
    float left   =-ratio;          //
47
    float right  = ratio;          // Create a new perspective projection matrix.
48
    float bottom = -1.0f;          //
49
    float top    =  1.0f;          // any change to those values will have serious consequences!
50
    float near, far;
51

    
52
    if( mFOV>0.0f )  // perspective projection
53
      {
54
      near= (float)(top / Math.tan(mFOV*Math.PI/360));
55
      mDistance = (int)(mHeight*near/(top-bottom));
56
      far = 2*mDistance-near;
57

    
58
      if( far<=0 )
59
        {
60
        android.util.Log.e("FBO", "error: far<=0. width="+mWidth+" height="+mHeight+
61
                           " mFOV="+mFOV+" mDistance="+mDistance+" far="+far+" near="+near);
62
        }
63
      else
64
        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
65
      }
66
    else                      // parallel projection
67
      {
68
      near= (float)(top / Math.tan(Math.PI/360));
69
      mDistance = (int)(mHeight*near/(top-bottom));
70
      far = 2*mDistance-near;
71

    
72
      Matrix.orthoM(mProjectionMatrix, 0, -mWidth/2, mWidth/2,-mHeight/2, mHeight/2, near, far);
73
      }
74

    
75
    mDepth = (int)((far-near)/2);
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
// must be called form a thread holding OpenGL Context
80

    
81
  private boolean createFBO()
82
    {
83
    int[] textureIds = new int[1];
84
    GLES20.glGenTextures(1, textureIds, 0);
85
    mTextureID = textureIds[0];
86
    int[] mFBORenderToTexture = new int[1];
87

    
88
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
89
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
90
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
91
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
92
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
93
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
94

    
95
    GLES20.glGenFramebuffers(1, mFBORenderToTexture, 0);
96
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBORenderToTexture[0]);
97
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mTextureID, 0);
98
    int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
99

    
100
    if(status != GLES20.GL_FRAMEBUFFER_COMPLETE)
101
      {
102
      android.util.Log.e("RenderTarget", "failed to create framebuffer, error="+status);
103

    
104
      GLES20.glDeleteTextures(1, textureIds, 0);
105
      GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
106
      mFramebufferID = 0;
107
      mTextureID = TEXTURE_FAILED_TO_CREATE;
108
      return false;
109
      }
110

    
111
    mFramebufferID = mFBORenderToTexture[0];
112

    
113
    android.util.Log.e("FBO", "creating ("+mWidth+","+mHeight+") "+mFramebufferID);
114

    
115
    return true;
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// must be called form a thread holding OpenGL Context
120

    
121
  private void deleteFBO()
122
    {
123
    android.util.Log.e("FBO", "deleting ("+mWidth+","+mHeight+") "+mFramebufferID);
124

    
125
    int[] textureIds = new int[1];
126
    int[] mFBORenderToTexture = new int[1];
127

    
128
    textureIds[0] = mTextureID;
129
    mFBORenderToTexture[0] = mFramebufferID;
130

    
131
    GLES20.glDeleteTextures(1, textureIds, 0);
132
    GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
133

    
134
    mFramebufferID = 0;
135
    mTextureID = TEXTURE_NOT_CREATED_YET;
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139
// must be called from a thread holding OpenGL Context
140

    
141
  void release()
142
    {
143
    if( mTextureID>=0 ) deleteFBO();
144

    
145
    mProjectionMatrix = null;
146
    mMarked = false;
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
  void reset()
152
    {
153
    mTextureID = TEXTURE_NOT_CREATED_YET;
154
    }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
// PUBLIC API
158

    
159
  public DistortedFramebuffer(int width, int height)
160
    {
161
    mProjectionMatrix = new float[16];
162

    
163
    mHeight        = height;
164
    mWidth         = width;
165
    mFramebufferID = -1;
166
    mTextureID     = TEXTURE_NOT_CREATED_YET;
167
    mFOV           = 60.0f;
168
    mX             = 0.0f;
169
    mY             = 0.0f;
170

    
171
    mMarked = false;
172

    
173
    createProjection();
174

    
175
    DistortedFramebufferList.add(this);
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  public DistortedFramebuffer(int fbo)
181
    {
182
    mProjectionMatrix = new float[16];
183

    
184
    mFramebufferID = fbo;
185
    mTextureID     = TEXTURE_DONT_CREATE;
186
    mFOV           = 60.0f;
187
    mX             = 0.0f;
188
    mY             = 0.0f;
189

    
190
    mMarked = false;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  public void markForDeletion()
196
    {
197
    android.util.Log.e("FBO", "marking for deletion ("+mWidth+","+mHeight+") "+mFramebufferID);
198

    
199
    DistortedFramebufferList.markForDeletion();
200
    mMarked = true;
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

    
205
  public void setProjection(float FOV, float x, float y)
206
    {
207
    mFOV = FOV;
208
    mX   = x;
209
    mY   = y;
210

    
211
    createProjection();
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  public void resize(int width, int height)
217
    {
218
    if( mWidth!=width || mHeight!=height )
219
      {
220
      mWidth = width;
221
      mHeight= height;
222

    
223
      createProjection();
224

    
225
      if( mTextureID>0 ) markForDeletion();
226
      }
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  public int getFBO()
232
    {
233
    return mFramebufferID;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// set this as Render Target to draw to. Must be called from a thread holding OpenGL context.
238

    
239
  public void setOutput()
240
    {
241
    if( mTextureID==TEXTURE_NOT_CREATED_YET ) createFBO();
242

    
243
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebufferID);
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
// set this as Render Target to draw from. Must be called from a thread holding OpenGL context.
248

    
249
  public void setInput()
250
    {
251
    if( mTextureID==TEXTURE_NOT_CREATED_YET ) createFBO();
252

    
253
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
254
    }
255

    
256
  }
(6-6/19)