Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedFramebuffer.java @ 64a642c1

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[] texIds = new int[1];
84
    int[] fboIds = new int[1];
85

    
86
    GLES20.glGenTextures(1, texIds, 0);
87
    mTextureID = texIds[0];
88

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

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

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

    
105
      GLES20.glDeleteTextures(1, texIds, 0);
106
      GLES20.glDeleteFramebuffers(1, fboIds, 0);
107
      mFramebufferID = 0;
108
      mTextureID = TEXTURE_FAILED_TO_CREATE;
109
      return false;
110
      }
111

    
112
    mFramebufferID = fboIds[0];
113

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

    
116
    return true;
117
    }
118

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

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

    
126
    int[] texIds = new int[1];
127
    int[] fboIds = new int[1];
128

    
129
    texIds[0] = mTextureID;
130
    fboIds[0] = mFramebufferID;
131

    
132
    GLES20.glDeleteTextures(1, texIds, 0);
133
    GLES20.glDeleteFramebuffers(1, fboIds, 0);
134

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

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

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

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

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

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

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
// PUBLIC API
159

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

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

    
172
    mMarked = false;
173

    
174
    createProjection();
175

    
176
    DistortedFramebufferList.add(this);
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

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

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

    
191
    mMarked = false;
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

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

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

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

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

    
212
    createProjection();
213
    }
214

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

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

    
224
      createProjection();
225

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

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

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

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

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

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

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

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

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

    
257
  }
(6-6/19)