Project

General

Profile

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

library / src / main / java / org / distorted / library / Distorted.java @ 1942537e

1 d333eb6b 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 6a06a912 Leszek Koltunski
package org.distorted.library;
21
22
import java.io.BufferedReader;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.InputStreamReader;
26
27 7845dc66 Leszek Koltunski
import android.content.Context;
28 6a06a912 Leszek Koltunski
import android.opengl.GLES20;
29
import android.os.Build;
30
import android.util.Log;
31
32
import org.distorted.library.exception.*;
33
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
/**
36
 * A singleton class used to control various global settings.
37
 */
38
public class Distorted 
39 39cbf9dc Leszek Koltunski
  {
40 6a06a912 Leszek Koltunski
  /**
41 e8c81a8e Leszek Koltunski
   * When creating an instance of a DistortedObject from another instance, do not clone anything.
42 6a06a912 Leszek Koltunski
   * Used in the copy constructor.
43
   */
44
  public static final int CLONE_NOTHING = 0x0;
45
  /**
46
   * When creating an instance of a DistortedObject from another instance, clone the Bitmap that's
47
   * backing up our DistortedObject. 
48
   * <p>
49
   * This way we can have two DistortedObjects, both backed up by the same Bitmap, to which we can 
50
   * apply different effects. Used in the copy constructor.
51
   */
52
  public static final int CLONE_BITMAP  = 0x1;
53
  /**
54 015642fb Leszek Koltunski
   * When creating an instance of a DistortedObject from another instance, clone the Matrix Effects.
55 6a06a912 Leszek Koltunski
   * <p>
56
   * This way we can have two different DistortedObjects with different Bitmaps behind them, both 
57
   * always displayed in exactly the same place on the screen. Applying any matrix-based effect to 
58
   * one of them automatically applies the effect to the other. Used in the copy constructor.
59
   */
60 015642fb Leszek Koltunski
  public static final int CLONE_MATRIX = 0x2;
61 6a06a912 Leszek Koltunski
  /**
62
   * When creating an instance of a DistortedObject from another instance, clone the Vertex Effects.
63
   * <p>
64
   * This way we can have two different DistortedObjects with different Bitmaps behind them, both 
65
   * always with the same Vertex effects. Applying any vertex-based effect to one of them automatically 
66
   * applies the effect to the other. Used in the copy constructor.
67
   */
68
  public static final int CLONE_VERTEX  = 0x4;
69
  /**
70
   * When creating an instance of a DistortedObject from another instance, clone the Fragment Effects.
71
   * <p>
72
   * This way we can have two different DistortedObjects with different Bitmaps behind them, both 
73
   * always with the same Fragment effects. Applying any fragment-based effect to one of them automatically 
74
   * applies the effect to the other. Used in the copy constructor.
75
   */
76
  public static final int CLONE_FRAGMENT= 0x8;
77
  /**
78 b455eb48 Leszek Koltunski
   * When creating an instance of a DistortedObjectTree from another instance, clone the children Nodes.
79 6a06a912 Leszek Koltunski
   * <p>
80
   * This is mainly useful for creating many similar sub-trees of Bitmaps and rendering then at different places
81
   * on the screen, with (optionally) different effects of the top-level root Bitmap.   
82
   */
83
  public static final int CLONE_CHILDREN= 0x10;
84 b3618cb5 Leszek Koltunski
85 6a06a912 Leszek Koltunski
  private static final String TAG = Distorted.class.getSimpleName();
86
  private static boolean mInitialized = false;
87 57578636 Leszek Koltunski
88 3f3bf7dc Leszek Koltunski
  static int mPositionH;       // model position information
89
  static int mNormalH;         // model normal information.
90
  static int mTextureCoordH;   // model texture coordinate information.
91 6a06a912 Leszek Koltunski
92 98455aa2 Leszek Koltunski
  static DistortedFramebuffer mFramebuffer = new DistortedFramebuffer(0); // output to the screen
93 bd3da5b2 Leszek Koltunski
94 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
95
96
  private Distorted()
97
    {
98
    
99
    }
100
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102
  
103
  private static void sanitizeMaxValues() throws VertexUniformsException,FragmentUniformsException
104
    {
105
    int maxV,maxF;  
106
    int[] param = new int[1];
107
    
108
    GLES20.glGetIntegerv(GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, param, 0);
109
    maxV = param[0];
110
    GLES20.glGetIntegerv(GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, param, 0);
111
    maxF = param[0];
112
    
113
    Log.d(TAG, "Max vectors in vertex shader: "+maxV);
114
    Log.d(TAG, "Max vectors in fragment shader: "+maxF);
115
    
116 8e34674e Leszek Koltunski
    if( !Build.FINGERPRINT.contains("generic") )
117 6a06a912 Leszek Koltunski
      {
118
      int realMaxV = (maxV-11)/4;   // adjust this in case of changes to the shaders...
119
      int realMaxF = (maxF- 2)/4;   //
120
    
121 71887484 Leszek Koltunski
      if( getMaxVertex()   > realMaxV )
122 6a06a912 Leszek Koltunski
        {
123
        throw new VertexUniformsException("Too many effects in the vertex shader, max is "+realMaxV, realMaxV);
124
        }
125 71887484 Leszek Koltunski
      if( getMaxFragment() > realMaxF )
126 6a06a912 Leszek Koltunski
        {
127
        throw new FragmentUniformsException("Too many effects in the fragment shader, max is "+realMaxF, realMaxF);
128
        }
129
      }
130
    }
131
  
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133
134
  private static int compileShader(final int shaderType, final String shaderSource) throws FragmentCompilationException,VertexCompilationException
135
    {
136
    int shaderHandle = GLES20.glCreateShader(shaderType);
137
138
    if (shaderHandle != 0) 
139
      {
140
      GLES20.glShaderSource(shaderHandle, "#version 100 \n"+ generateShaderHeader(shaderType) + shaderSource);
141
      GLES20.glCompileShader(shaderHandle);
142
      final int[] compileStatus = new int[1];
143
      GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
144
145
      if (compileStatus[0] != GLES20.GL_TRUE ) 
146
        {
147
        GLES20.glDeleteShader(shaderHandle);
148
        shaderHandle = 0;
149
        }
150
      }
151
152
    if (shaderHandle == 0)
153
      {     
154
      String error = GLES20.glGetShaderInfoLog(shaderHandle);
155
     
156
      switch(shaderType)
157
        {
158
        case GLES20.GL_VERTEX_SHADER  : throw new VertexCompilationException(error); 
159
        case GLES20.GL_FRAGMENT_SHADER: throw new FragmentCompilationException(error);
160
        default                       : throw new RuntimeException(error);
161
        }
162
      }
163
164
    return shaderHandle;
165
    }
166
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168
169
  private static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) throws LinkingException
170
    {
171
    int programHandle = GLES20.glCreateProgram();
172
173
    if (programHandle != 0) 
174
      {
175
      GLES20.glAttachShader(programHandle, vertexShaderHandle);         
176
      GLES20.glAttachShader(programHandle, fragmentShaderHandle);
177
178
      if (attributes != null)
179
        {
180
        final int size = attributes.length;
181
182
        for (int i = 0; i < size; i++)
183
          {
184
          GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
185
          }                
186
        }
187
188
      GLES20.glLinkProgram(programHandle);
189
190
      final int[] linkStatus = new int[1];
191
      GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
192
193
      if (linkStatus[0] != GLES20.GL_TRUE ) 
194
        {         
195
        String error = GLES20.glGetProgramInfoLog(programHandle);
196
        GLES20.glDeleteProgram(programHandle);
197
        throw new LinkingException(error);
198
        }
199
      
200
      final int[] numberOfUniforms = new int[1];
201
      GLES20.glGetProgramiv(programHandle, GLES20.GL_ACTIVE_UNIFORMS, numberOfUniforms, 0);
202
203
      android.util.Log.d(TAG, "number of active uniforms="+numberOfUniforms[0]);
204
      }
205
 
206
    return programHandle;
207
    }
208
 
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210
  
211
  private static String generateShaderHeader(final int type)
212
    {
213
    String header="";
214
   
215
    switch(type)
216
      {
217 71887484 Leszek Koltunski
      case GLES20.GL_VERTEX_SHADER  : header += ("#define NUM_VERTEX "  + getMaxVertex()+"\n");
218 6a06a912 Leszek Koltunski
     
219
                                      for(EffectNames name: EffectNames.values() )
220
                                        {
221 1e438fc7 Leszek Koltunski
                                        if( name.getType()==EffectTypes.VERTEX)
222 6a06a912 Leszek Koltunski
                                        header += ("#define "+name.name()+" "+name.ordinal()+"\n");  
223
                                        }
224
                                      break;
225 71887484 Leszek Koltunski
      case GLES20.GL_FRAGMENT_SHADER: header += ("#define NUM_FRAGMENT "+ getMaxFragment()+"\n");
226 6a06a912 Leszek Koltunski
     
227
                                      for(EffectNames name: EffectNames.values() )
228
                                        {
229 1e438fc7 Leszek Koltunski
                                        if( name.getType()==EffectTypes.FRAGMENT)
230 6a06a912 Leszek Koltunski
                                        header += ("#define "+name.name()+" "+name.ordinal()+"\n");  
231
                                        }
232
                                      break;
233
     }
234
   
235
    //Log.d(TAG,""+header);
236
    
237
    return header;
238
    }
239
  
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
  
242 7845dc66 Leszek Koltunski
  private static String readTextFileFromRawResource(final Context c, final int resourceId)
243 6a06a912 Leszek Koltunski
    {
244 7845dc66 Leszek Koltunski
    final InputStream inputStream = c.getResources().openRawResource(resourceId);
245 6a06a912 Leszek Koltunski
    final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
246
    final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
247
 
248
    String nextLine;
249
    final StringBuilder body = new StringBuilder();
250
 
251
    try
252
      {
253
      while ((nextLine = bufferedReader.readLine()) != null)
254
        {
255
        body.append(nextLine);
256
        body.append('\n');
257
        }
258
      }
259
    catch (IOException e)
260
      {
261
      return null;
262
      }
263
 
264
    return body.toString();
265
    }
266
 
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268
 
269 7845dc66 Leszek Koltunski
  private static String getVertexShader(final Context c)
270 6a06a912 Leszek Koltunski
    {
271 7845dc66 Leszek Koltunski
    return readTextFileFromRawResource( c, R.raw.main_vertex_shader);
272 6a06a912 Leszek Koltunski
    }
273
 
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
 
276 7845dc66 Leszek Koltunski
  private static String getFragmentShader(final Context c)
277 6a06a912 Leszek Koltunski
    {
278 7845dc66 Leszek Koltunski
    return readTextFileFromRawResource( c, R.raw.main_fragment_shader);
279 6a06a912 Leszek Koltunski
    }
280
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282
// Public API
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
/**
285 98455aa2 Leszek Koltunski
 * Sets Vertical Field of View angle and the point the camera is looking at. This changes the Projection Matrix.
286 6a06a912 Leszek Koltunski
 *   
287
 * @param fov Vertical Field Of View angle, in degrees. If T is the middle of the top edge of the 
288
 *            screen, E is the eye point, and B is the middle of the bottom edge of the screen, then 
289
 *            fov = angle(TEB)
290 98455aa2 Leszek Koltunski
 * @param x   X-coordinate of the point the camera is looking at. -scrWidth/2 &lt; x &lt; scrWidth/2
291
 * @param y   Y-coordinate of the point the camera is looking at. -scrHeight/2 &lt; y &lt; scrHeight/2
292 6a06a912 Leszek Koltunski
 */
293 98455aa2 Leszek Koltunski
  public static void setProjection(float fov, float x, float y)
294 6a06a912 Leszek Koltunski
    {
295 98455aa2 Leszek Koltunski
    mFramebuffer.setProjection(fov,x,y);
296 6a06a912 Leszek Koltunski
    }
297
  
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299
/**
300
 * When OpenGL context gets created, you need to call this method so that the library can initialise its internal data structures.
301
 * I.e. best called from GLSurfaceView.onSurfaceCreated().
302
 * <p>
303
 * Compiles the vertex and fragment shaders, establishes the addresses of all uniforms, and initialises all Bitmaps that have already
304
 * been created.
305
 *   
306 015642fb Leszek Koltunski
 * @param context Context of the App using the library - used to open up Resources and read Shader code.
307 6a06a912 Leszek Koltunski
 * @throws FragmentCompilationException
308
 * @throws VertexCompilationException
309
 * @throws VertexUniformsException
310
 * @throws FragmentUniformsException
311
 * @throws LinkingException
312
 */
313 7845dc66 Leszek Koltunski
  public static void onSurfaceCreated(final Context context) throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
314 6a06a912 Leszek Koltunski
    { 
315
    mInitialized = true;  
316 f6fb3c6d Leszek Koltunski
317 7845dc66 Leszek Koltunski
    final String vertexShader   = Distorted.getVertexShader(context);
318
    final String fragmentShader = Distorted.getFragmentShader(context);
319 f6fb3c6d Leszek Koltunski
320 6a06a912 Leszek Koltunski
    sanitizeMaxValues();
321
    
322
    final int vertexShaderHandle   = compileShader(GLES20.GL_VERTEX_SHADER  , vertexShader  );     
323
    final int fragmentShaderHandle = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);     
324
      
325 3f3bf7dc Leszek Koltunski
    int programH = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[] {"a_Position",  "a_Color", "a_Normal", "a_TexCoordinate"});
326 57578636 Leszek Koltunski
327
    mFramebuffer.setProjection(60.0f,0.0f,0.0f);
328
329 3f3bf7dc Leszek Koltunski
    GLES20.glUseProgram(programH);
330 57578636 Leszek Koltunski
331 3f3bf7dc Leszek Koltunski
    int textureUniformH = GLES20.glGetUniformLocation(programH, "u_Texture");
332
    mPositionH          = GLES20.glGetAttribLocation( programH, "a_Position");
333
    mNormalH            = GLES20.glGetAttribLocation( programH, "a_Normal");
334
    mTextureCoordH      = GLES20.glGetAttribLocation( programH, "a_TexCoordinate");
335 57578636 Leszek Koltunski
336 6a06a912 Leszek Koltunski
    GLES20.glEnable (GLES20.GL_DEPTH_TEST);
337
    GLES20.glDepthFunc(GLES20.GL_LEQUAL);
338
    GLES20.glEnable(GLES20.GL_BLEND);
339
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
340 0ce6fcef Leszek Koltunski
    GLES20.glEnable(GLES20.GL_CULL_FACE);
341
    GLES20.glCullFace(GLES20.GL_BACK);
342 5bf698ee Leszek Koltunski
    GLES20.glFrontFace(GLES20.GL_CW);
343 57578636 Leszek Koltunski
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
344 3f3bf7dc Leszek Koltunski
    GLES20.glUniform1i(textureUniformH, 0);
345 8c893ffc Leszek Koltunski
346 3f3bf7dc Leszek Koltunski
    EffectQueueFragment.getUniforms(programH);
347
    EffectQueueVertex.getUniforms(programH);
348
    EffectQueueMatrix.getUniforms(programH);
349 6a06a912 Leszek Koltunski
    
350
    GLES20.glEnableVertexAttribArray(mPositionH);        
351
    GLES20.glEnableVertexAttribArray(mNormalH);
352
    GLES20.glEnableVertexAttribArray(mTextureCoordH);
353
   
354 b455eb48 Leszek Koltunski
    DistortedObjectTree.reset();
355 6a06a912 Leszek Koltunski
    EffectMessageSender.startSending();
356
    }
357
  
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359
/**
360
 * Call this when the physical size of the surface we are rendering to changes.
361
 * I.e. must be called from GLSurfaceView.onSurfaceChanged()  
362
 *   
363
 * @param surfaceWidth  new width of the surface.
364
 * @param surfaceHeight new height of the surface.
365
 */
366
  public static void onSurfaceChanged(int surfaceWidth, int surfaceHeight)
367
    {
368 ed13a5de Leszek Koltunski
    mFramebuffer.resize(surfaceWidth,surfaceHeight);
369 6a06a912 Leszek Koltunski
    }
370
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372
/**
373
 * Call this so that the Library can release its internal data structures.
374
 * Must be called from Activity.onDestroy(). 
375
 */
376
  public static void onDestroy()
377
    {
378 4e2382f3 Leszek Koltunski
    DistortedTexture.release();
379 8e34674e Leszek Koltunski
    DistortedFramebuffer.release();
380 b455eb48 Leszek Koltunski
    DistortedObjectTree.release();
381 8e34674e Leszek Koltunski
    EffectQueue.release();
382 1942537e Leszek Koltunski
    DistortedEffectQueues.release();
383 6a06a912 Leszek Koltunski
    EffectMessageSender.stopSending();
384
   
385
    mInitialized = false;
386
    }
387
  
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389
/**
390
 * Returns the true if onSurfaceCreated has been called already, and thus if the Library's is ready
391
 * to accept effect requests.
392
 * 
393
 * @return <code>true</code> if the Library is ready for action, <code>false</code> otherwise.
394
 */
395
  public static boolean isInitialized()
396
    {
397
    return mInitialized;  
398
    }
399
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401
/**
402 1e438fc7 Leszek Koltunski
 * Returns the maximum number of Matrix effects.
403 6a06a912 Leszek Koltunski
 *    
404 1e438fc7 Leszek Koltunski
 * @return The maximum number of Matrix effects
405 6a06a912 Leszek Koltunski
 */
406 1e438fc7 Leszek Koltunski
  public static int getMaxMatrix()
407 6a06a912 Leszek Koltunski
    {
408 71887484 Leszek Koltunski
    return EffectQueue.getMax(EffectTypes.MATRIX.ordinal());
409 6a06a912 Leszek Koltunski
    }
410
 
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412
/**
413
 * Returns the maximum number of Vertex effects.
414
 *    
415
 * @return The maximum number of Vertex effects
416
 */  
417
  public static int getMaxVertex()
418
    {
419 71887484 Leszek Koltunski
    return EffectQueue.getMax(EffectTypes.VERTEX.ordinal());
420 6a06a912 Leszek Koltunski
    }
421
  
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423
/**
424
 * Returns the maximum number of Fragment effects.
425
 *    
426
 * @return The maximum number of Fragment effects
427
 */  
428
  public static int getMaxFragment()
429
    {
430 71887484 Leszek Koltunski
    return EffectQueue.getMax(EffectTypes.FRAGMENT.ordinal());
431 6a06a912 Leszek Koltunski
    }
432 71887484 Leszek Koltunski
433 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
434
/**
435 71887484 Leszek Koltunski
 * Sets the maximum number of Matrix effects that can be applied to a single DistortedObject at one time.
436 61ec8208 Leszek Koltunski
 * This can fail if:
437
 * <ul>
438
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
439
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
440
 *     before the Vertex Shader gets compiled, i.e. before the call to {@link #onSurfaceCreated}. After this
441
 *     time only decreasing the value of 'max' is permitted.
442
 * <li>Furthermore, this needs to be called before any DistortedObject gets created.
443
 * </ul>
444 6a06a912 Leszek Koltunski
 * 
445 1e438fc7 Leszek Koltunski
 * @param max new maximum number of simultaneous Matrix Effects. Has to be a non-negative number not greater
446 6a06a912 Leszek Koltunski
 *            than Byte.MAX_VALUE 
447
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
448
 */
449 1e438fc7 Leszek Koltunski
  public static boolean setMaxMatrix(int max)
450 6a06a912 Leszek Koltunski
    {
451 71887484 Leszek Koltunski
    return EffectQueue.setMax(EffectTypes.MATRIX.ordinal(),max);
452 6a06a912 Leszek Koltunski
    }
453
  
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455
/**
456 71887484 Leszek Koltunski
 * Sets the maximum number of Vertex effects that can be applied to a single DistortedObject at one time.
457 6a06a912 Leszek Koltunski
 * This can fail if:
458
 * <ul>
459 61ec8208 Leszek Koltunski
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
460 6a06a912 Leszek Koltunski
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called 
461
 *     before the Vertex Shader gets compiled, i.e. before the call to {@link #onSurfaceCreated}. After this
462 61ec8208 Leszek Koltunski
 *     time only decreasing the value of 'max' is permitted.
463
* <li>Furthermore, this needs to be called before any DistortedObject gets created.
464 6a06a912 Leszek Koltunski
 * </ul>
465
 * 
466
 * @param max new maximum number of simultaneous Vertex Effects. Has to be a non-negative number not greater
467
 *            than Byte.MAX_VALUE 
468
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
469
 */
470
  public static boolean setMaxVertex(int max)
471
    {
472 71887484 Leszek Koltunski
    return EffectQueue.setMax(EffectTypes.VERTEX.ordinal(),max);
473 6a06a912 Leszek Koltunski
    }
474
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476
/**
477 71887484 Leszek Koltunski
 * Sets the maximum number of Fragment effects that can be applied to a single DistortedObject at one time.
478 6a06a912 Leszek Koltunski
 * This can fail if:
479
 * <ul>
480 61ec8208 Leszek Koltunski
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
481 6a06a912 Leszek Koltunski
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called 
482
 *     before the Fragment Shader gets compiled, i.e. before the call to {@link #onSurfaceCreated}. After this
483 61ec8208 Leszek Koltunski
 *     time only decreasing the value of 'max' is permitted.
484
 * <li>Furthermore, this needs to be called before any DistortedObject gets created.
485 6a06a912 Leszek Koltunski
 * </ul>
486
 * 
487
 * @param max new maximum number of simultaneous Fragment Effects. Has to be a non-negative number not greater
488
 *            than Byte.MAX_VALUE 
489
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
490
 */
491
  public static boolean setMaxFragment(int max)
492
    {
493 71887484 Leszek Koltunski
    return EffectQueue.setMax(EffectTypes.FRAGMENT.ordinal(),max);
494 6a06a912 Leszek Koltunski
    }
495 39cbf9dc Leszek Koltunski
  }