Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedTexture.java @ e7a20702

1 4e2382f3 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
import android.graphics.Bitmap;
23
import android.graphics.Matrix;
24
import android.opengl.GLES20;
25
import android.opengl.GLUtils;
26
27 1942537e Leszek Koltunski
import java.util.Iterator;
28
import java.util.LinkedList;
29 4e2382f3 Leszek Koltunski
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31 e0b6c593 Leszek Koltunski
/**
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 4e2382f3 Leszek Koltunski
public class DistortedTexture
43
  {
44 1942537e Leszek Koltunski
  private static boolean mListMarked = false;
45
  private static LinkedList<DistortedTexture> mList = new LinkedList<>();
46 4e2382f3 Leszek Koltunski
47 f8686932 Leszek Koltunski
  private static int mTextureH;
48
49 3ef3364d Leszek Koltunski
  private int mSizeX, mSizeY;  // in screen space
50
  float mHalfX, mHalfY;        // halves of the above
51 4e2382f3 Leszek Koltunski
  private long mID;
52 1942537e Leszek Koltunski
  private boolean mMarked;
53 4e2382f3 Leszek Koltunski
54 e7a20702 Leszek Koltunski
  private Bitmap mBmp= null;
55
  private int[] mTextureDataH;
56
  private boolean mBitmapSet;
57 4e2382f3 Leszek Koltunski
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59
// We have to flip vertically every single Bitmap that we get fed with.
60
//
61
// Reason: textures read from files are the only objects in OpenGL which have their origins at the
62
// upper-left corner. Everywhere else the origin is in the lower-left corner. Thus we have to flip.
63
// The alternative solution, namely inverting the y-coordinate of the TexCoord does not really work-
64
// i.e. it works only in case of rendering directly to the screen, but if we render to an FBO and
65 421c2728 Leszek Koltunski
// then take the FBO and render to screen, (DistortedTree does so!) things get inverted as textures
66 4e2382f3 Leszek Koltunski
// created from FBO have their origins in the lower-left... Mindfuck!
67
68
  private static Bitmap flipBitmap(Bitmap src)
69
    {
70
    Matrix matrix = new Matrix();
71
    matrix.preScale(1.0f,-1.0f);
72
73
    return Bitmap.createBitmap(src,0,0,src.getWidth(),src.getHeight(), matrix,true);
74
    }
75
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77 1942537e Leszek Koltunski
// must be called from a thread holding OpenGL Context
78 4e2382f3 Leszek Koltunski
79 1942537e Leszek Koltunski
  void createTexture()
80 4e2382f3 Leszek Koltunski
    {
81 e7a20702 Leszek Koltunski
    if( mBmp!=null && mTextureDataH!=null )
82 4e2382f3 Leszek Koltunski
      {
83 1942537e Leszek Koltunski
      //android.util.Log.e("Texture", "creating "+mID);
84
85 4e2382f3 Leszek Koltunski
      if( mTextureDataH[0]==0 ) GLES20.glGenTextures(1, mTextureDataH, 0);
86
87
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
88
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
89
      GLES20.glTexParameteri ( 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_CLAMP_TO_EDGE );
91
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
92
93 e7a20702 Leszek Koltunski
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, flipBitmap(mBmp), 0);
94
      mBmp = null;
95 4e2382f3 Leszek Koltunski
      }
96
    }
97
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99 1942537e Leszek Koltunski
// must be called from a thread holding OpenGL Context
100 4e2382f3 Leszek Koltunski
101 1942537e Leszek Koltunski
  private void deleteTexture()
102 4e2382f3 Leszek Koltunski
    {
103 1942537e Leszek Koltunski
    if( mTextureDataH!=null && mTextureDataH[0]>0 )
104
      {
105
      //android.util.Log.e("Texture", "deleting "+mID);
106 4e2382f3 Leszek Koltunski
107 1942537e Leszek Koltunski
      GLES20.glDeleteTextures(1, mTextureDataH, 0);
108 4e2382f3 Leszek Koltunski
109 1942537e Leszek Koltunski
      mTextureDataH[0] = 0;
110 e7a20702 Leszek Koltunski
      mBitmapSet= false;
111 1942537e Leszek Koltunski
      }
112
113
    mMarked = false;
114 4e2382f3 Leszek Koltunski
    }
115
116 d558d9bd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
117
118
  long getID()
119 1942537e Leszek Koltunski
    {
120
    return mID;
121
    }
122 d558d9bd Leszek Koltunski
123 e7a20702 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
124
125
  boolean setAsInput()
126
    {
127
    if( mBitmapSet )
128
      {
129
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
130
      return true;
131
      }
132
133
    return false;
134
    }
135
136 f8686932 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
137
138
  static void getUniforms(int mProgramH)
139
    {
140
    mTextureH= GLES20.glGetUniformLocation( mProgramH, "u_Texture");
141
142
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
143
    GLES20.glUniform1i(mTextureH, 0);
144
    }
145
146 4e2382f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
147
148 7b8086eb Leszek Koltunski
  static synchronized void onDestroy()
149 4e2382f3 Leszek Koltunski
    {
150 1942537e Leszek Koltunski
    mListMarked = false;
151
    mList.clear();
152 4e2382f3 Leszek Koltunski
    }
153
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155 1942537e Leszek Koltunski
// must be called form a thread holding OpenGL Context
156 4e2382f3 Leszek Koltunski
157 1942537e Leszek Koltunski
  static synchronized void deleteAllMarked()
158 4e2382f3 Leszek Koltunski
    {
159 1942537e Leszek Koltunski
    if( mListMarked )
160 4e2382f3 Leszek Koltunski
      {
161 1942537e Leszek Koltunski
      DistortedTexture tmp;
162
      Iterator<DistortedTexture> iterator = mList.iterator();
163
164
      while(iterator.hasNext())
165
        {
166
        tmp = iterator.next();
167
168
        if( tmp.mMarked )
169
          {
170
          tmp.deleteTexture();
171
          iterator.remove();
172
          }
173
        }
174 4e2382f3 Leszek Koltunski
175 1942537e Leszek Koltunski
      mListMarked = false;
176
      }
177 4e2382f3 Leszek Koltunski
    }
178
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
// PUBLIC API
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
/**
183
 * Create empty texture of given dimensions.
184
 */
185 3ef3364d Leszek Koltunski
  public DistortedTexture(int width, int height)
186 4e2382f3 Leszek Koltunski
    {
187 3ef3364d Leszek Koltunski
    mSizeX= width ; mHalfX = mSizeX/2.0f;
188
    mSizeY= height; mHalfY = mSizeY/2.0f;
189
190 4e2382f3 Leszek Koltunski
    mTextureDataH   = new int[1];
191
    mTextureDataH[0]= 0;
192 e7a20702 Leszek Koltunski
    mBmp            = null;
193
    mBitmapSet      = false;
194 1942537e Leszek Koltunski
    mID             = 0;
195
    mMarked         = false;
196 4e2382f3 Leszek Koltunski
197 1942537e Leszek Koltunski
    mList.add(this);
198 4e2382f3 Leszek Koltunski
    }
199
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201
/**
202 1942537e Leszek Koltunski
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
203 4e2382f3 Leszek Koltunski
 */
204 1942537e Leszek Koltunski
  public void markForDeletion()
205 4e2382f3 Leszek Koltunski
    {
206 1942537e Leszek Koltunski
    //android.util.Log.e("Texture", "marking for deletion "+mID);
207
208
    mListMarked = true;
209
    mMarked     = true;
210 4e2382f3 Leszek Koltunski
    }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
/**
214 1942537e Leszek Koltunski
 * Sets the underlying android.graphics.Bitmap object.
215 4e2382f3 Leszek Koltunski
 * <p>
216
 * You can only recycle() the passed Bitmap once the OpenGL context gets created (i.e. after call
217 432442f9 Leszek Koltunski
 * to GLSurfaceView.onSurfaceCreated) because only after this point can the Library upload it to the GPU!
218 4e2382f3 Leszek Koltunski
 *
219
 * @param bmp The android.graphics.Bitmap object to apply effects to and display.
220
 */
221
222
  public void setTexture(Bitmap bmp)
223
    {
224 e7a20702 Leszek Koltunski
    mBitmapSet = true;
225
    mBmp       = bmp;
226
    mID        = bmp.hashCode();
227 4e2382f3 Leszek Koltunski
228 1942537e Leszek Koltunski
    //android.util.Log.e("Texture", "setting new bitmap "+mID);
229 4e2382f3 Leszek Koltunski
    }
230
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232
/**
233 46e25345 Leszek Koltunski
 * Returns the height of the Texture.
234 4e2382f3 Leszek Koltunski
 *
235
 * @return height of the object, in pixels.
236
 */
237
  public int getWidth()
238 1942537e Leszek Koltunski
    {
239
    return mSizeX;
240
    }
241 4e2382f3 Leszek Koltunski
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243
/**
244 46e25345 Leszek Koltunski
 * Returns the width of the Texture.
245 4e2382f3 Leszek Koltunski
 *
246
 * @return width of the Object, in pixels.
247
 */
248
  public int getHeight()
249 1942537e Leszek Koltunski
    {
250
    return mSizeY;
251
    }
252 4e2382f3 Leszek Koltunski
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254
/**
255 46e25345 Leszek Koltunski
 * Returns the depth of the Texture.
256 3ef3364d Leszek Koltunski
 * <p>
257
 * Admittedly quite a strange method. Why do we need to pass a Grid to it? Because one cannot determine
258
 * 'depth' of a texture when rendered based only on the texture itself, that depends on the Grid it is
259
 * rendered with.
260 4e2382f3 Leszek Koltunski
 *
261
 * @return depth of the Object, in pixels.
262
 */
263 3ef3364d Leszek Koltunski
  public int getDepth(GridObject grid)
264 1942537e Leszek Koltunski
    {
265
    return grid==null ? 0 : (int)(mSizeX*grid.zFactor);
266
    }
267 4e2382f3 Leszek Koltunski
  }