Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedFramebuffer.java @ 7304d89f

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 float mX, mY;
34
  private float mFOV;
35

    
36
  private int[] texIds = new int[1];
37
  private int[] fboIds = new int[1];
38

    
39
  int mWidth,mHeight,mDepth,mDistance;
40
  float[] mProjectionMatrix;
41
  boolean mMarked;
42

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44

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

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

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

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

    
77
    mDepth = (int)((far-near)/2);
78
    }
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81
// must be called form a thread holding OpenGL Context
82

    
83
  private boolean createFBO()
84
    {
85
    GLES20.glGenTextures(1, texIds, 0);
86

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

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

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

    
103
      GLES20.glDeleteTextures(1, texIds, 0);
104
      GLES20.glDeleteFramebuffers(1, fboIds, 0);
105
      fboIds[0] = 0;
106
      texIds[0] = TEXTURE_FAILED_TO_CREATE;
107
      return false;
108
      }
109

    
110
    android.util.Log.e("FBO", "creating ("+mWidth+","+mHeight+") "+fboIds[0]);
111

    
112
    return true;
113
    }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116
// must be called form a thread holding OpenGL Context
117

    
118
  private void deleteFBO()
119
    {
120
    android.util.Log.e("FBO", "deleting ("+mWidth+","+mHeight+") "+fboIds[0]);
121

    
122
    GLES20.glDeleteTextures(1, texIds, 0);
123
    GLES20.glDeleteFramebuffers(1, fboIds, 0);
124

    
125
    fboIds[0] = 0;
126
    texIds[0] = TEXTURE_NOT_CREATED_YET;
127
    }
128

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130
// must be called from a thread holding OpenGL Context
131

    
132
  void release()
133
    {
134
    if( texIds[0]>=0 ) deleteFBO();
135

    
136
    mProjectionMatrix = null;
137
    mMarked = false;
138
    }
139

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

    
142
  void reset()
143
    {
144
    texIds[0] = TEXTURE_NOT_CREATED_YET;
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// PUBLIC API
149

    
150
  public DistortedFramebuffer(int width, int height)
151
    {
152
    mProjectionMatrix = new float[16];
153

    
154
    mHeight        = height;
155
    mWidth         = width;
156
    fboIds[0]      = -1;
157
    texIds[0]      = TEXTURE_NOT_CREATED_YET;
158
    mFOV           = 60.0f;
159
    mX             = 0.0f;
160
    mY             = 0.0f;
161

    
162
    mMarked = false;
163

    
164
    createProjection();
165

    
166
    DistortedFramebufferList.add(this);
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  public DistortedFramebuffer(int fbo)
172
    {
173
    mProjectionMatrix = new float[16];
174

    
175
    fboIds[0]      = fbo;
176
    texIds[0]      = TEXTURE_DONT_CREATE;
177
    mFOV           = 60.0f;
178
    mX             = 0.0f;
179
    mY             = 0.0f;
180

    
181
    mMarked = false;
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  public void markForDeletion()
187
    {
188
    android.util.Log.e("FBO", "marking for deletion ("+mWidth+","+mHeight+") "+fboIds[0]);
189

    
190
    DistortedFramebufferList.markForDeletion();
191
    mMarked = true;
192
    }
193

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

    
196
  public void setProjection(float FOV, float x, float y)
197
    {
198
    mFOV = FOV;
199
    mX   = x;
200
    mY   = y;
201

    
202
    createProjection();
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  public void resize(int width, int height)
208
    {
209
    if( mWidth!=width || mHeight!=height )
210
      {
211
      mWidth = width;
212
      mHeight= height;
213

    
214
      createProjection();
215

    
216
      if( texIds[0]>0 ) markForDeletion();
217
      }
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  public int getFBO()
223
    {
224
    return fboIds[0];
225
    }
226

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228
// set this as Render Target to draw to. Must be called from a thread holding OpenGL context.
229

    
230
  public void setOutput()
231
    {
232
    if( texIds[0]==TEXTURE_NOT_CREATED_YET ) createFBO();
233

    
234
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboIds[0]);
235
    }
236

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

    
240
  public void setInput()
241
    {
242
    if( texIds[0]==TEXTURE_NOT_CREATED_YET ) createFBO();
243

    
244
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texIds[0]);
245
    }
246

    
247
  }
(6-6/19)