Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedTexture.java @ 0c827acc

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.graphics.Bitmap;
23
import android.graphics.Matrix;
24
import android.opengl.GLES30;
25
import android.opengl.GLUtils;
26

    
27
import java.util.Iterator;
28
import java.util.LinkedList;
29

    
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31
/**
32
 * Class which represents a OpenGL Texture object.
33
 * <p>
34
 * Create a Texture of arbitrary size and feed some pixels to it via the setTexture() method.
35
 * <p>
36
 * Keep all objects created in a static LinkedList. The point: we need to be able to mark
37
 * Textures for deletion, and delete all marked objects later at a convenient time (that's
38
 * because we can only delete from a thread that holds the OpenGL context so here we provide a
39
 * framework where one is able to mark for deletion at any time and actual deletion takes place
40
 * on the next render).
41
 */
42
public class DistortedTexture
43
  {
44
  private static boolean mListMarked = false;
45
  private static LinkedList<DistortedTexture> mList = new LinkedList<>();
46

    
47
  private static int mTextureH;
48

    
49
  private int mSizeX, mSizeY;  // in screen space
50
  float mHalfX, mHalfY;        // halves of the above
51
  private long mID;
52
  private boolean mMarked;
53

    
54
  private Bitmap mBmp= null;
55
  private int[] mTextureDataH;
56

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58
// We have to flip vertically every single Bitmap that we get fed with.
59
//
60
// Reason: textures read from files are the only objects in OpenGL which have their origins at the
61
// upper-left corner. Everywhere else the origin is in the lower-left corner. Thus we have to flip.
62
// The alternative solution, namely inverting the y-coordinate of the TexCoord does not really work-
63
// i.e. it works only in case of rendering directly to the screen, but if we render to an FBO and
64
// then take the FBO and render to screen, (DistortedTree does so!) things get inverted as textures
65
// created from FBO have their origins in the lower-left... Mindfuck!
66

    
67
  private static Bitmap flipBitmap(Bitmap src)
68
    {
69
    Matrix matrix = new Matrix();
70
    matrix.preScale(1.0f,-1.0f);
71

    
72
    return Bitmap.createBitmap(src,0,0,src.getWidth(),src.getHeight(), matrix,true);
73
    }
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76
// must be called from a thread holding OpenGL Context
77

    
78
  void createTexture()
79
    {
80
    if( mBmp!=null && mTextureDataH!=null )
81
      {
82
      //android.util.Log.e("Texture", "creating "+mID);
83

    
84
      if( mTextureDataH[0]==0 )
85
        {
86
        GLES30.glGenTextures(1, mTextureDataH, 0);
87
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureDataH[0]);
88
        GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR );
89
        GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR );
90
        GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE );
91
        GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE );
92
        GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, flipBitmap(mBmp), 0);
93
        }
94
      else
95
        {
96
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureDataH[0]);
97
        GLUtils.texSubImage2D(GLES30.GL_TEXTURE_2D, 0,0,0,flipBitmap(mBmp));
98
        }
99

    
100
      mBmp = null;
101
      }
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
// must be called from a thread holding OpenGL Context
106

    
107
  private void deleteTexture()
108
    {
109
    if( mTextureDataH!=null && mTextureDataH[0]>0 )
110
      {
111
      //android.util.Log.e("Texture", "deleting "+mID);
112

    
113
      GLES30.glDeleteTextures(1, mTextureDataH, 0);
114

    
115
      mTextureDataH[0] = 0;
116
      mID              = 0;
117
      }
118

    
119
    mMarked = false;
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  long getID()
125
    {
126
    return mID;
127
    }
128

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

    
131
  boolean setAsInput()
132
    {
133
    if( mID!=0 )
134
      {
135
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureDataH[0]);
136
      return true;
137
      }
138

    
139
    return false;
140
    }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  static void getUniforms(int mProgramH)
145
    {
146
    mTextureH= GLES30.glGetUniformLocation( mProgramH, "u_Texture");
147

    
148
    GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
149
    GLES30.glUniform1i(mTextureH, 0);
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  static synchronized void onDestroy()
155
    {
156
    mListMarked = false;
157
    mList.clear();
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161
// must be called form a thread holding OpenGL Context
162

    
163
  static synchronized void deleteAllMarked()
164
    {
165
    if( mListMarked )
166
      {
167
      DistortedTexture tmp;
168
      Iterator<DistortedTexture> iterator = mList.iterator();
169

    
170
      while(iterator.hasNext())
171
        {
172
        tmp = iterator.next();
173

    
174
        if( tmp.mMarked )
175
          {
176
          tmp.deleteTexture();
177
          iterator.remove();
178
          }
179
        }
180

    
181
      mListMarked = false;
182
      }
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
// PUBLIC API
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188
/**
189
 * Create empty texture of given dimensions.
190
 */
191
  public DistortedTexture(int width, int height)
192
    {
193
    mSizeX= width ; mHalfX = mSizeX/2.0f;
194
    mSizeY= height; mHalfY = mSizeY/2.0f;
195

    
196
    mTextureDataH   = new int[1];
197
    mTextureDataH[0]= 0;
198
    mBmp            = null;
199
    mID             = 0;
200
    mMarked         = false;
201

    
202
    mList.add(this);
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
/**
207
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
208
 */
209
  public void markForDeletion()
210
    {
211
    //android.util.Log.e("Texture", "marking for deletion "+mID);
212

    
213
    mListMarked = true;
214
    mMarked     = true;
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
/**
219
 * Sets the underlying android.graphics.Bitmap object.
220
 * <p>
221
 * You can only recycle() the passed Bitmap once the OpenGL context gets created (i.e. after call
222
 * to GLSurfaceView.onSurfaceCreated) because only after this point can the Library upload it to the GPU!
223
 *
224
 * @param bmp The android.graphics.Bitmap object to apply effects to and display.
225
 */
226

    
227
  public void setTexture(Bitmap bmp)
228
    {
229
    mBmp= bmp;
230
    mID = bmp.hashCode();
231

    
232
    //android.util.Log.e("Texture", "setting new bitmap "+mID);
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236
/**
237
 * Returns the height of the Texture.
238
 *
239
 * @return height of the object, in pixels.
240
 */
241
  public int getWidth()
242
    {
243
    return mSizeX;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
/**
248
 * Returns the width of the Texture.
249
 *
250
 * @return width of the Object, in pixels.
251
 */
252
  public int getHeight()
253
    {
254
    return mSizeY;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
/**
259
 * Returns the depth of the Texture.
260
 * <p>
261
 * Admittedly quite a strange method. Why do we need to pass a Mesh to it? Because one cannot determine
262
 * 'depth' of a texture when rendered based only on the texture itself, that depends on the Mesh it is
263
 * rendered with.
264
 *
265
 * @return depth of the Object, in pixels.
266
 */
267
  public int getDepth(MeshObject mesh)
268
    {
269
    return mesh==null ? 0 : (int)(mSizeX*mesh.zFactor);
270
    }
271
  }
(4-4/16)