Project

General

Profile

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

library / src / main / java / org / distorted / library / main / DistortedEffects.java @ c41d046c

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.main;
21

    
22
import android.content.res.Resources;
23
import android.opengl.GLES31;
24
import android.util.Log;
25

    
26
import org.distorted.library.R;
27
import org.distorted.library.effect.Effect;
28
import org.distorted.library.effect.EffectName;
29
import org.distorted.library.effect.EffectType;
30
import org.distorted.library.effect.FragmentEffect;
31
import org.distorted.library.effect.VertexEffect;
32
import org.distorted.library.message.EffectListener;
33
import org.distorted.library.program.DistortedProgram;
34
import org.distorted.library.program.FragmentCompilationException;
35
import org.distorted.library.program.FragmentUniformsException;
36
import org.distorted.library.program.LinkingException;
37
import org.distorted.library.program.VertexCompilationException;
38
import org.distorted.library.program.VertexUniformsException;
39

    
40
import java.io.InputStream;
41
import java.nio.ByteBuffer;
42
import java.nio.ByteOrder;
43
import java.nio.FloatBuffer;
44
import java.nio.IntBuffer;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47
/**
48
 * Class containing Matrix, Vertex, Fragment and Postprocessing effect queues.
49
 * <p>
50
 * The queues hold actual effects to be applied to a given (InputSurface,MeshObject) combo.
51
 */
52
public class DistortedEffects
53
  {
54
  /// MAIN PROGRAM ///
55
  private static DistortedProgram mMainProgram;
56
  private static int mMainTextureH;
57

    
58
  /// BLIT PROGRAM ///
59
  private static DistortedProgram mBlitProgram;
60
  private static int mBlitTextureH;
61
  private static int mBlitDepthH;
62
  private static final FloatBuffer mQuadPositions;
63

    
64
  static
65
    {
66
    float[] positionData= { -0.5f, -0.5f,  -0.5f, 0.5f,  0.5f,-0.5f,  0.5f, 0.5f };
67
    mQuadPositions = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()).asFloatBuffer();
68
    mQuadPositions.put(positionData).position(0);
69
    }
70

    
71
  /// OIT CLEAR PROGRAM ///
72
  private static DistortedProgram mOITClearProgram;
73
  private static int mOITClearDepthH;
74
  private static int mOITClearTexCorrH;
75
  private static int mOITClearSizeH;
76

    
77
  /// OIT BUILD PROGRAM ///
78
  private static DistortedProgram mOITBuildProgram;
79
  private static int mOITBuildTextureH;
80
  private static int mOITBuildDepthTextureH;
81
  private static int mOITBuildDepthH;
82
  private static int mOITBuildTexCorrH;
83
  private static int mOITBuildSizeH;
84
  private static int mOITBuildNumRecordsH;
85

    
86
  private static int[] mLinkedListSSBO = new int[1];
87
  private static int[] mAtomicCounter = new int[1];
88

    
89
  static
90
    {
91
    mLinkedListSSBO[0]= -1;
92
    mAtomicCounter[0] = -1;
93
    }
94

    
95
  private static int mBufferSize=(0x1<<23);  // 8 million entries
96

    
97
  /// OIT RENDER PROGRAM ///
98
  private static DistortedProgram mOITRenderProgram;
99
  private static int mOITRenderTextureH;
100
  private static int mOITRenderDepthTextureH;
101
  private static int mOITRenderDepthH;
102
  private static int mOITRenderTexCorrH;
103
  private static int mOITRenderSizeH;
104

    
105
  /// NORMAL PROGRAM /////
106
  private static DistortedProgram mNormalProgram;
107
  private static int mNormalMVPMatrixH;
108
  /// END PROGRAMS //////
109

    
110
  private static long mNextID =0;
111
  private long mID;
112

    
113
  private EffectQueueMatrix mM;
114
  private EffectQueueFragment mF;
115
  private EffectQueueVertex mV;
116
  private EffectQueuePostprocess mP;
117

    
118
  private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

    
122
  static void createProgram(Resources resources)
123
  throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
124
    {
125
    // MAIN PROGRAM ////////////////////////////////////
126
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
127
    final InputStream mainFragStream = resources.openRawResource(R.raw.main_fragment_shader);
128

    
129
    int numF = FragmentEffect.getNumEnabled();
130
    int numV = VertexEffect.getNumEnabled();
131

    
132
    String mainVertHeader= Distorted.GLSL_VERSION + ("#define NUM_VERTEX "   + ( numV>0 ? getMax(EffectType.VERTEX  ) : 0 ) + "\n");
133
    String mainFragHeader= Distorted.GLSL_VERSION + ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n");
134
    String enabledEffectV= VertexEffect.getGLSL();
135
    String enabledEffectF= FragmentEffect.getGLSL();
136

    
137
    //android.util.Log.e("Effects", "vertHeader= "+mainVertHeader);
138
    //android.util.Log.e("Effects", "fragHeader= "+mainFragHeader);
139
    //android.util.Log.e("Effects", "enabledV= "+enabledEffectV);
140
    //android.util.Log.e("Effects", "enabledF= "+enabledEffectF);
141

    
142
    String[] feedback = { "v_Position", "v_endPosition" };
143

    
144
    try
145
      {
146
      mMainProgram = new DistortedProgram(mainVertStream, mainFragStream, mainVertHeader, mainFragHeader,
147
                                          enabledEffectV, enabledEffectF, Distorted.GLSL, feedback);
148
      }
149
    catch(Exception e)
150
      {
151
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile MAIN program: "+e.getMessage());
152
      throw new RuntimeException(e.getMessage());
153
      }
154

    
155
    int mainProgramH = mMainProgram.getProgramHandle();
156
    EffectQueueFragment.getUniforms(mainProgramH);
157
    EffectQueueVertex.getUniforms(mainProgramH);
158
    EffectQueueMatrix.getUniforms(mainProgramH);
159
    mMainTextureH= GLES31.glGetUniformLocation( mainProgramH, "u_Texture");
160

    
161
    // BLIT PROGRAM ////////////////////////////////////
162
    final InputStream blitVertStream = resources.openRawResource(R.raw.blit_vertex_shader);
163
    final InputStream blitFragStream = resources.openRawResource(R.raw.blit_fragment_shader);
164

    
165
    try
166
      {
167
      mBlitProgram = new DistortedProgram(blitVertStream,blitFragStream,Distorted.GLSL_VERSION,Distorted.GLSL_VERSION, Distorted.GLSL);
168
      }
169
    catch(Exception e)
170
      {
171
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile BLIT program: "+e.getMessage());
172
      throw new RuntimeException(e.getMessage());
173
      }
174

    
175
    int blitProgramH = mBlitProgram.getProgramHandle();
176
    mBlitTextureH  = GLES31.glGetUniformLocation( blitProgramH, "u_Texture");
177
    mBlitDepthH    = GLES31.glGetUniformLocation( blitProgramH, "u_Depth");
178

    
179
    // OIT CLEAR PROGRAM ////////////////////////////////////
180
    final InputStream oitClearVertStream = resources.openRawResource(R.raw.oit_vertex_shader);
181
    final InputStream oitClearFragStream = resources.openRawResource(R.raw.oit_clear_fragment_shader);
182

    
183
    try
184
      {
185
      mOITClearProgram = new DistortedProgram(oitClearVertStream,oitClearFragStream,Distorted.GLSL_VERSION,Distorted.GLSL_VERSION, Distorted.GLSL);
186
      }
187
    catch(Exception e)
188
      {
189
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile OIT CLEAR program: "+e.getMessage());
190
      throw new RuntimeException(e.getMessage());
191
      }
192

    
193
    int oitClearProgramH   = mOITClearProgram.getProgramHandle();
194
    mOITClearDepthH        = GLES31.glGetUniformLocation( oitClearProgramH, "u_Depth");
195
    mOITClearTexCorrH      = GLES31.glGetUniformLocation( oitClearProgramH, "u_TexCorr");
196
    mOITClearSizeH         = GLES31.glGetUniformLocation( oitClearProgramH, "u_Size");
197

    
198
    // OIT BUILD PROGRAM ////////////////////////////////////
199
    final InputStream oitBuildVertStream = resources.openRawResource(R.raw.oit_vertex_shader);
200
    final InputStream oitBuildFragStream = resources.openRawResource(R.raw.oit_build_fragment_shader);
201

    
202
    try
203
      {
204
      mOITBuildProgram = new DistortedProgram(oitBuildVertStream,oitBuildFragStream,Distorted.GLSL_VERSION,Distorted.GLSL_VERSION, Distorted.GLSL);
205
      }
206
    catch(Exception e)
207
      {
208
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile OIT BUILD program: "+e.getMessage());
209
      throw new RuntimeException(e.getMessage());
210
      }
211

    
212
    int oitBuildProgramH   = mOITBuildProgram.getProgramHandle();
213
    mOITBuildTextureH      = GLES31.glGetUniformLocation( oitBuildProgramH, "u_Texture");
214
    mOITBuildDepthTextureH = GLES31.glGetUniformLocation( oitBuildProgramH, "u_DepthTexture");
215
    mOITBuildDepthH        = GLES31.glGetUniformLocation( oitBuildProgramH, "u_Depth");
216
    mOITBuildTexCorrH      = GLES31.glGetUniformLocation( oitBuildProgramH, "u_TexCorr");
217
    mOITBuildSizeH         = GLES31.glGetUniformLocation( oitBuildProgramH, "u_Size");
218
    mOITBuildNumRecordsH   = GLES31.glGetUniformLocation( oitBuildProgramH, "u_numRecords");
219

    
220
    if( mLinkedListSSBO[0]<0 )
221
      {
222
      GLES31.glGenBuffers(1,mLinkedListSSBO,0);
223
      GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, mLinkedListSSBO[0]);
224
      GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
225
      GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, mBufferSize*4 , null, GLES31.GL_DYNAMIC_READ|GLES31.GL_DYNAMIC_DRAW);
226
      GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
227
      }
228

    
229
    if( mAtomicCounter[0]<0 )
230
      {
231
      GLES31.glGenBuffers(1,mAtomicCounter,0);
232
      GLES31.glBindBufferBase(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0, mAtomicCounter[0]);
233
      GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, mAtomicCounter[0] );
234
      GLES31.glBufferData(GLES31.GL_ATOMIC_COUNTER_BUFFER, 4, null, GLES31.GL_DYNAMIC_DRAW);
235
      GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0);
236
      }
237

    
238
    // BLIT DEPTH RENDER PROGRAM ///////////////////////////
239
    final InputStream oitRenderVertStream = resources.openRawResource(R.raw.oit_vertex_shader);
240
    final InputStream oitRenderFragStream = resources.openRawResource(R.raw.oit_render_fragment_shader);
241

    
242
    try
243
      {
244
      mOITRenderProgram = new DistortedProgram(oitRenderVertStream,oitRenderFragStream,Distorted.GLSL_VERSION,Distorted.GLSL_VERSION, Distorted.GLSL);
245
      }
246
    catch(Exception e)
247
      {
248
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile OIT RENDER program: "+e.getMessage());
249
      throw new RuntimeException(e.getMessage());
250
      }
251

    
252
    int oitRenderProgramH   = mOITRenderProgram.getProgramHandle();
253
    mOITRenderTextureH      = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Texture");
254
    mOITRenderDepthTextureH = GLES31.glGetUniformLocation( oitRenderProgramH, "u_DepthTexture");
255
    mOITRenderDepthH        = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Depth");
256
    mOITRenderTexCorrH      = GLES31.glGetUniformLocation( oitRenderProgramH, "u_TexCorr");
257
    mOITRenderSizeH         = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Size");
258

    
259
    // NORMAL PROGRAM //////////////////////////////////////
260
    final InputStream normalVertexStream   = resources.openRawResource(R.raw.normal_vertex_shader);
261
    final InputStream normalFragmentStream = resources.openRawResource(R.raw.normal_fragment_shader);
262

    
263
    try
264
      {
265
      mNormalProgram = new DistortedProgram(normalVertexStream,normalFragmentStream, Distorted.GLSL_VERSION, Distorted.GLSL_VERSION, Distorted.GLSL);
266
      }
267
    catch(Exception e)
268
      {
269
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile NORMAL program: "+e.getMessage());
270
      throw new RuntimeException(e.getMessage());
271
      }
272

    
273
    int normalProgramH = mNormalProgram.getProgramHandle();
274
    mNormalMVPMatrixH  = GLES31.glGetUniformLocation( normalProgramH, "u_MVPMatrix");
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  private void initializeEffectLists(DistortedEffects d, int flags)
280
    {
281
    if( (flags & Distorted.CLONE_MATRIX) != 0 )
282
      {
283
      mM = d.mM;
284
      matrixCloned = true;
285
      }
286
    else
287
      {
288
      mM = new EffectQueueMatrix(mID);
289
      matrixCloned = false;
290
      }
291
    
292
    if( (flags & Distorted.CLONE_VERTEX) != 0 )
293
      {
294
      mV = d.mV;
295
      vertexCloned = true;
296
      }
297
    else
298
      {
299
      mV = new EffectQueueVertex(mID);
300
      vertexCloned = false;
301
      }
302
    
303
    if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
304
      {
305
      mF = d.mF;
306
      fragmentCloned = true;
307
      }
308
    else
309
      {
310
      mF = new EffectQueueFragment(mID);
311
      fragmentCloned = false;
312
      }
313

    
314
    if( (flags & Distorted.CLONE_POSTPROCESS) != 0 )
315
      {
316
      mP = d.mP;
317
      postprocessCloned = true;
318
      }
319
    else
320
      {
321
      mP = new EffectQueuePostprocess(mID);
322
      postprocessCloned = false;
323
      }
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  EffectQueuePostprocess getPostprocess()
329
    {
330
    return mP;
331
    }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
  void newNode(DistortedNode node)
336
    {
337
    mM.newNode(node);
338
    mF.newNode(node);
339
    mV.newNode(node);
340
    mP.newNode(node);
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  private void displayNormals(MeshObject mesh)
346
    {
347
    GLES31.glBindBufferBase(GLES31.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mesh.mAttTFO[0]);
348
    GLES31.glBeginTransformFeedback( GLES31.GL_POINTS);
349
    DistortedRenderState.switchOffDrawing();
350
    GLES31.glDrawArrays( GLES31.GL_POINTS, 0, mesh.numVertices);
351
    DistortedRenderState.restoreDrawing();
352
    GLES31.glEndTransformFeedback();
353
    GLES31.glBindBufferBase(GLES31.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
354

    
355
    mNormalProgram.useProgram();
356
    GLES31.glUniformMatrix4fv(mNormalMVPMatrixH, 1, false, mM.getMVP() , 0);
357
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttTFO[0]);
358
    GLES31.glVertexAttribPointer(mNormalProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, 0, 0);
359
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
360
    GLES31.glLineWidth(8.0f);
361
    GLES31.glDrawArrays(GLES31.GL_LINES, 0, 2*mesh.numVertices);
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime, float marginInPixels)
367
    {
368
    float halfZ = halfW*mesh.zFactor;
369

    
370
    mM.compute(currTime);
371
    mV.compute(currTime,halfW,halfH,halfZ);
372
    mF.compute(currTime,halfW,halfH);
373
    mP.compute(currTime);
374

    
375
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
376

    
377
    mMainProgram.useProgram();
378
    GLES31.glUniform1i(mMainTextureH, 0);
379

    
380
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttVBO[0]);
381
    GLES31.glVertexAttribPointer(mMainProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET0);
382
    GLES31.glVertexAttribPointer(mMainProgram.mAttribute[1], MeshObject.NOR_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET1);
383
    GLES31.glVertexAttribPointer(mMainProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET2);
384
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
385

    
386
    mM.send(surface,halfW,halfH,halfZ,marginInPixels);
387
    mV.send();
388
    mF.send();
389

    
390
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
391

    
392
    if( mesh.mShowNormals ) displayNormals(mesh);
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396
/**
397
 * Only for use by the library itself.
398
 *
399
 * @y.exclude
400
 */
401
  public static void blitPriv(DistortedOutputSurface surface)
402
    {
403
    mBlitProgram.useProgram();
404

    
405
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
406
    GLES31.glUniform1i(mBlitTextureH, 0);
407
    GLES31.glUniform1f( mBlitDepthH , 1.0f-surface.mNear);
408
    GLES31.glVertexAttribPointer(mBlitProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
409
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413
// reset atomic counter to 0
414

    
415
  static void zeroOutAtomic()
416
    {
417
    GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, mAtomicCounter[0] );
418

    
419
    ByteBuffer atomicBuf = (ByteBuffer)GLES31.glMapBufferRange( GLES31.GL_ATOMIC_COUNTER_BUFFER, 0, 4,
420
                                                                GLES31.GL_MAP_WRITE_BIT|GLES31.GL_MAP_INVALIDATE_BUFFER_BIT);
421
    if( atomicBuf!=null )
422
      {
423
      IntBuffer atomicIntBuf = atomicBuf.order(ByteOrder.nativeOrder()).asIntBuffer();
424

    
425
      //int counter = atomicIntBuf.get(0);
426
      //android.util.Log.e("counter", "now = "+counter+" w="+surface.mWidth+" h="+surface.mHeight
427
      //                             +" diff="+(counter-surface.mWidth*surface.mHeight));
428
      atomicIntBuf.put(0,0);
429
      }
430
    else
431
      {
432
      android.util.Log.e("effects", "failed to map atomic buffer");
433
      }
434

    
435
    GLES31.glUnmapBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER);
436
    GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0);
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440
// Pass1 of the OIT algorithm. Clear per-pixel head-poiners.
441

    
442
  static void oitClear(DistortedOutputSurface surface)
443
    {
444
    mOITClearProgram.useProgram();
445

    
446
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
447
    GLES31.glUniform2f(mOITClearTexCorrH, 1.0f, 1.0f );   // corrections do not really matter here - only present because of common vertex shader.
448
    GLES31.glUniform1f( mOITClearDepthH , 1.0f);          // likewise depth
449
    GLES31.glUniform2f(mOITClearSizeH, surface.mWidth, surface.mHeight);
450
    GLES31.glVertexAttribPointer(mOITClearProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
451
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455
// Pass2 of the OIT algorithm - build per-pixel linked lists.
456

    
457
  static void oitBuild(DistortedOutputSurface surface, float corrW, float corrH)
458
    {
459
    mOITBuildProgram.useProgram();
460

    
461
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
462
    GLES31.glUniform1i(mOITBuildTextureH, 0);
463
    GLES31.glUniform1i(mOITBuildDepthTextureH, 1);
464
    GLES31.glUniform2f(mOITBuildTexCorrH, corrW, corrH );
465
    GLES31.glUniform2f(mOITBuildSizeH, surface.mWidth, surface.mHeight);
466
    GLES31.glUniform1ui(mOITBuildNumRecordsH, (mBufferSize-surface.mWidth*surface.mHeight)/3 );  // see the fragment shader
467
    GLES31.glUniform1f(mOITBuildDepthH , 1.0f-surface.mNear);
468
    GLES31.glVertexAttribPointer(mOITBuildProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
469
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
470
    }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473
// Pass3 of the OIT algorithm. Render all the transparent pixels from the per-pixel linked lists.
474

    
475
  static void oitRender(DistortedOutputSurface surface, float corrW, float corrH)
476
    {
477
    mOITRenderProgram.useProgram();
478

    
479
    //analyzeBuffer(surface.mWidth, surface.mHeight);
480

    
481
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
482
    GLES31.glUniform1i(mOITRenderTextureH, 0);
483
    GLES31.glUniform1i(mOITRenderDepthTextureH, 1);
484
    GLES31.glUniform2f(mOITRenderTexCorrH, corrW, corrH );
485
    GLES31.glUniform2f(mOITRenderSizeH, surface.mWidth, surface.mHeight);
486
    GLES31.glUniform1f( mOITRenderDepthH , 1.0f-surface.mNear);
487
    GLES31.glVertexAttribPointer(mOITRenderProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
488
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
489
    }
490

    
491
///////////////////////////////////////////////////////////////////////////////////////////////////
492

    
493
  private static void analyzeBuffer(int w, int h)
494
    {
495
    int ptr, index;
496
    int errors = 0;
497

    
498
    GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
499
    ByteBuffer buf = (ByteBuffer)GLES31.glMapBufferRange(GLES31.GL_SHADER_STORAGE_BUFFER, 0, mBufferSize*4, GLES31.GL_MAP_READ_BIT);
500
    IntBuffer intBuf = buf.order(ByteOrder.nativeOrder()).asIntBuffer();
501

    
502
    for(int col=0; col<w; col++)
503
      for(int row=0; row<h; row++)
504
        {
505
        index = col+row*w;
506
        ptr = intBuf.get(index);
507

    
508
        if( ptr!=0 )
509
          {
510
          if( ptr>0 && ptr<mBufferSize )
511
            {
512
            ptr = intBuf.get(ptr);
513
            if( ptr != index )
514
              {
515
              android.util.Log.d("surface", "col="+col+" row="+row+" val="+ptr+" expected: "+index);
516
              errors++;
517
              }
518
            }
519
          else
520
            {
521
            android.util.Log.d("surface", "overflow!");
522
            }
523
          }
524
        }
525

    
526
    GLES31.glUnmapBuffer(GLES31.GL_SHADER_STORAGE_BUFFER);
527
    GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
528

    
529
    if( errors>0 ) android.util.Log.e("surface", "errors: "+errors);
530
    }
531

    
532
///////////////////////////////////////////////////////////////////////////////////////////////////
533

    
534
  private void releasePriv()
535
    {
536
    if( !matrixCloned   )   mM.abortAll(false);
537
    if( !vertexCloned   )   mV.abortAll(false);
538
    if( !fragmentCloned )   mF.abortAll(false);
539
    if( !postprocessCloned) mP.abortAll(false);
540

    
541
    mM = null;
542
    mV = null;
543
    mF = null;
544
    mP = null;
545
    }
546

    
547
///////////////////////////////////////////////////////////////////////////////////////////////////
548

    
549
  static void onPause()
550
    {
551
    mLinkedListSSBO[0]= -1;
552
    mAtomicCounter[0] = -1;
553
    }
554

    
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

    
557
  static void onDestroy()
558
    {
559
    mNextID =  0;
560
    }
561

    
562
///////////////////////////////////////////////////////////////////////////////////////////////////
563
// PUBLIC API
564
///////////////////////////////////////////////////////////////////////////////////////////////////
565
/**
566
 * Create empty effect queue.
567
 */
568
  public DistortedEffects()
569
    {
570
    mID = ++mNextID;
571
    initializeEffectLists(this,0);
572
    }
573

    
574
///////////////////////////////////////////////////////////////////////////////////////////////////
575
/**
576
 * Copy constructor.
577
 * <p>
578
 * Whatever we do not clone gets created just like in the default constructor.
579
 *
580
 * @param dc    Source object to create our object from
581
 * @param flags A bitmask of values specifying what to copy.
582
 *              For example, CLONE_VERTEX | CLONE_MATRIX.
583
 */
584
  public DistortedEffects(DistortedEffects dc, int flags)
585
    {
586
    mID = ++mNextID;
587
    initializeEffectLists(dc,flags);
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591
/**
592
 * Releases all resources. After this call, the queue should not be used anymore.
593
 */
594
  @SuppressWarnings("unused")
595
  public synchronized void delete()
596
    {
597
    releasePriv();
598
    }
599

    
600
///////////////////////////////////////////////////////////////////////////////////////////////////
601
/**
602
 * Returns unique ID of this instance.
603
 *
604
 * @return ID of the object.
605
 */
606
  public long getID()
607
      {
608
      return mID;
609
      }
610

    
611
///////////////////////////////////////////////////////////////////////////////////////////////////
612
/**
613
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
614
 * to one of the Effects in our queues. Nothing will happen if 'el' is already in the list.
615
 * 
616
 * @param el A class implementing the EffectListener interface that wants to get notifications.
617
 */
618
  @SuppressWarnings("unused")
619
  public void registerForMessages(EffectListener el)
620
    {
621
    mM.registerForMessages(el);
622
    mV.registerForMessages(el);
623
    mF.registerForMessages(el);
624
    mP.registerForMessages(el);
625
    }
626

    
627
///////////////////////////////////////////////////////////////////////////////////////////////////
628
/**
629
 * Removes the calling class from the list of Listeners that get notified if something happens to Effects in our queue.
630
 * 
631
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
632
 */
633
  @SuppressWarnings("unused")
634
  public void deregisterForMessages(EffectListener el)
635
    {
636
    mM.deregisterForMessages(el);
637
    mV.deregisterForMessages(el);
638
    mF.deregisterForMessages(el);
639
    mP.deregisterForMessages(el);
640
    }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643
/**
644
 * Aborts all Effects.
645
 * @return Number of effects aborted.
646
 */
647
  public int abortAllEffects()
648
    {
649
    return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
650
    }
651

    
652
///////////////////////////////////////////////////////////////////////////////////////////////////
653
/**
654
 * Aborts all Effects of a given type, for example all MATRIX Effects.
655
 * 
656
 * @param type one of the constants defined in {@link EffectType}
657
 * @return Number of effects aborted.
658
 */
659
  public int abortByType(EffectType type)
660
    {
661
    switch(type)
662
      {
663
      case MATRIX     : return mM.abortAll(true);
664
      case VERTEX     : return mV.abortAll(true);
665
      case FRAGMENT   : return mF.abortAll(true);
666
      case POSTPROCESS: return mP.abortAll(true);
667
      default         : return 0;
668
      }
669
    }
670

    
671
///////////////////////////////////////////////////////////////////////////////////////////////////
672
/**
673
 * Aborts an Effect by its ID.
674
 *
675
 * @param id the Id of the Effect to be removed, as returned by getID().
676
 * @return Number of effects aborted.
677
 */
678
  public int abortById(long id)
679
    {
680
    long type = id&EffectType.MASK;
681

    
682
    if( type == EffectType.MATRIX.ordinal()      ) return mM.removeById(id);
683
    if( type == EffectType.VERTEX.ordinal()      ) return mV.removeById(id);
684
    if( type == EffectType.FRAGMENT.ordinal()    ) return mF.removeById(id);
685
    if( type == EffectType.POSTPROCESS.ordinal() ) return mP.removeById(id);
686

    
687
    return 0;
688
    }
689

    
690
///////////////////////////////////////////////////////////////////////////////////////////////////
691
/**
692
 * Aborts a single Effect.
693
 * 
694
 * @param effect the Effect we want to abort.
695
 * @return number of Effects aborted. Always either 0 or 1.
696
 */
697
  public int abortEffect(Effect effect)
698
    {
699
    switch(effect.getType())
700
      {
701
      case MATRIX     : return mM.removeEffect(effect);
702
      case VERTEX     : return mV.removeEffect(effect);
703
      case FRAGMENT   : return mF.removeEffect(effect);
704
      case POSTPROCESS: return mP.removeEffect(effect);
705
      default         : return 0;
706
      }
707
    }
708

    
709
///////////////////////////////////////////////////////////////////////////////////////////////////
710
/**
711
 * Abort all Effects of a given name, for example all rotations.
712
 * 
713
 * @param name one of the constants defined in {@link EffectName}
714
 * @return number of Effects aborted.
715
 */
716
  public int abortByName(EffectName name)
717
    {
718
    switch(name.getType())
719
      {
720
      case MATRIX     : return mM.removeByName(name);
721
      case VERTEX     : return mV.removeByName(name);
722
      case FRAGMENT   : return mF.removeByName(name);
723
      case POSTPROCESS: return mP.removeByName(name);
724
      default                : return 0;
725
      }
726
    }
727

    
728
///////////////////////////////////////////////////////////////////////////////////////////////////
729
/**
730
 * Returns the maximum number of effects of a given type that can be simultaneously applied to a
731
 * single (InputSurface,MeshObject) combo.
732
 *
733
 * @param type {@link EffectType}
734
 * @return The maximum number of effects of a given type.
735
 */
736
  @SuppressWarnings("unused")
737
  public static int getMax(EffectType type)
738
    {
739
    return EffectQueue.getMax(type.ordinal());
740
    }
741

    
742
///////////////////////////////////////////////////////////////////////////////////////////////////
743
/**
744
 * Sets the maximum number of effects that can be stored in a single EffectQueue at one time.
745
 * This can fail if:
746
 * <ul>
747
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
748
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
749
 *     before the Vertex Shader gets compiled, i.e. before the call to {@link Distorted#onCreate}. After this
750
 *     time only decreasing the value of 'max' is permitted.
751
 * <li>Furthermore, this needs to be called before any instances of the DistortedEffects class get created.
752
 * </ul>
753
 *
754
 * @param type {@link EffectType}
755
 * @param max new maximum number of simultaneous effects. Has to be a non-negative number not greater
756
 *            than Byte.MAX_VALUE
757
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
758
 */
759
  @SuppressWarnings("unused")
760
  public static boolean setMax(EffectType type, int max)
761
    {
762
    return EffectQueue.setMax(type.ordinal(),max);
763
    }
764

    
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766
/**
767
 * Add a new Effect to our queue.
768
 *
769
 * @param effect The Effect to add.
770
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
771
 */
772
  public boolean apply(Effect effect)
773
    {
774
    switch(effect.getType())
775
      {
776
      case MATRIX      : return mM.add(effect);
777
      case VERTEX      : return mV.add(effect);
778
      case FRAGMENT    : return mF.add(effect);
779
      case POSTPROCESS : return mP.add(effect);
780
      }
781

    
782
    return false;
783
    }
784
  }
(2-2/21)