Project

General

Profile

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

library / src / main / java / org / distorted / library / effect / PostprocessEffect.java @ 2f1f7570

1 8eccf334 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2017 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.effect;
21
22 9e771d06 Leszek Koltunski
import org.distorted.library.main.DistortedFramebuffer;
23 86d322b5 Leszek Koltunski
import org.distorted.library.main.DistortedMaster;
24 aa2f0486 Leszek Koltunski
import org.distorted.library.program.DistortedProgram;
25 1dfc9074 leszek
26 2f1f7570 Leszek Koltunski
import java.lang.reflect.Method;
27 1dfc9074 leszek
import java.nio.ByteBuffer;
28
import java.nio.ByteOrder;
29
import java.nio.FloatBuffer;
30 aa2f0486 Leszek Koltunski
import java.util.ArrayList;
31 1dfc9074 leszek
32 8eccf334 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
33 faa3ff56 Leszek Koltunski
/**
34 a20f274f Leszek Koltunski
 * Abstract class that represents an Effect that works by running a certain Shader Program(s) on a Framebuffer.
35 faa3ff56 Leszek Koltunski
 */
36 86d322b5 Leszek Koltunski
public abstract class PostprocessEffect extends Effect implements DistortedMaster.Slave
37 8eccf334 Leszek Koltunski
  {
38 86d322b5 Leszek Koltunski
  private static final int MIPMAP = 0;
39 faa3ff56 Leszek Koltunski
/**
40
 * 5: 5 per-effect interpolated values.
41
 */
42
  public static final int NUM_UNIFORMS = 5;
43 125cee3d Leszek Koltunski
44 faa3ff56 Leszek Koltunski
  static final int POS_DATA_SIZE= 2;
45
  static final int TEX_DATA_SIZE= 2;
46 1dfc9074 leszek
47
  static final FloatBuffer mQuadPositions, mQuadTexture, mQuadTextureInv;
48
49
  static
50
    {
51
    int dataLength      = 4;
52
    int bytes_per_float = 4;
53
54
    float[] position  = { -0.5f, -0.5f,  -0.5f, 0.5f,  0.5f,-0.5f,  0.5f, 0.5f };
55
    float[] textureNor= {  0.0f,  0.0f,   0.0f, 1.0f,  1.0f, 0.0f,  1.0f, 1.0f };
56
    float[] textureInv= {  0.0f,  0.0f,   1.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f };
57
58
    mQuadPositions = ByteBuffer.allocateDirect(POS_DATA_SIZE*dataLength*bytes_per_float).order(ByteOrder.nativeOrder()).asFloatBuffer();
59
    mQuadPositions.put(position).position(0);
60 031fbe7a Leszek Koltunski
    mQuadTexture   = ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*bytes_per_float).order(ByteOrder.nativeOrder()).asFloatBuffer();
61 1dfc9074 leszek
    mQuadTexture.put(textureNor).position(0);
62
    mQuadTextureInv= ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*bytes_per_float).order(ByteOrder.nativeOrder()).asFloatBuffer();
63
    mQuadTextureInv.put(textureInv).position(0);
64
    }
65
66 aa2f0486 Leszek Koltunski
  private static class Source
67
    {
68
    private String mName, mVertexShader, mFragmentShader;
69
70 86d322b5 Leszek Koltunski
    Source(String name, String vertex, String fragment)
71 aa2f0486 Leszek Koltunski
      {
72
      mName           = name;
73
      mVertexShader   = vertex;
74
      mFragmentShader = fragment;
75
      }
76
    }
77
78
  static ArrayList<DistortedProgram> mPrograms = new ArrayList<>();
79
  private static ArrayList<Source> mSources = new ArrayList<>();
80
  private static int mNumSources = 0;
81
82 86d322b5 Leszek Koltunski
  private class Job
83
    {
84
    int type;
85
    int level;
86
87
    Job(int t, int l)
88
      {
89
      type = t;
90
      level= l;
91
      }
92
    }
93
94
  private ArrayList<Job> mJobs = new ArrayList<>();
95
96
  int mQualityLevel;
97
  float mQualityScale;
98
99 aa2f0486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
100
101
  static int register(final String name, final String vertexShader, final String fragmentShader)
102
    {
103
    mSources.add(new Source(name,vertexShader,fragmentShader));
104
105
    return mNumSources++;
106
    }
107
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109 faa3ff56 Leszek Koltunski
/**
110
 * Only for use by the library itself.
111
 *
112
 * @y.exclude
113
 */
114 aa2f0486 Leszek Koltunski
  public static void createPrograms()
115
    {
116
    Source source;
117
    int len = mSources.size();
118
119
    for(int i=0; i<len; i++)
120
      {
121
      source = mSources.remove(0);
122
123 faa3ff56 Leszek Koltunski
      //android.util.Log.d("postprocess", "compiling: "+source.mName);
124 aa2f0486 Leszek Koltunski
125
      try
126
        {
127
        mPrograms.add (new DistortedProgram(source.mVertexShader,source.mFragmentShader));
128
        }
129
      catch(Exception e)
130
        {
131
        android.util.Log.e("Effects", "exception trying to compile "+source.mName+" program: "+e.getMessage());
132
        throw new RuntimeException(e.getMessage());
133
        }
134
      }
135
    }
136
137 1dfc9074 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
138 faa3ff56 Leszek Koltunski
/**
139
 * Only for use by the library itself.
140
 *
141
 * @y.exclude
142
 */
143 9e771d06 Leszek Koltunski
  public abstract int apply(float[] uniforms, int index, DistortedFramebuffer buffer);
144 86d322b5 Leszek Koltunski
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146 9e771d06 Leszek Koltunski
  /**
147
   * Only for use by the library itself.
148
   *
149
   * @y.exclude
150
   */
151
  public abstract boolean getRender();
152 7266d8ef Leszek Koltunski
153 247d8225 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
154
  /**
155
   * Only for use by the library itself.
156
   *
157
   * @y.exclude
158
   */
159 9e771d06 Leszek Koltunski
  public int getQuality()
160 247d8225 Leszek Koltunski
    {
161 9e771d06 Leszek Koltunski
    return mQualityLevel;
162 247d8225 Leszek Koltunski
    }
163
164 86d322b5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
165
/**
166
 * This is not really part of the public API. Has to be public only because it is a part of the
167
 * DistortedSlave interface, which should really be a class that we extend here instead but
168
 * Java has no multiple inheritance.
169
 *
170
 * @y.exclude
171
 */
172
  public void doWork()
173
    {
174
    int num = mJobs.size();
175
    Job job;
176
177
    for(int i=0; i<num; i++)
178
      {
179
      job = mJobs.remove(0);
180
181
      switch(job.type)
182
        {
183
        case MIPMAP: int level = job.level;
184
                     mQualityLevel = level;
185
                     mQualityScale = 1.0f;
186
                     for(int j=0; j<level; j++) mQualityScale*= EffectQuality.MULTIPLIER;
187
                     break;
188
        }
189
      }
190
    }
191 1dfc9074 leszek
192 2f1f7570 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
193
194
  static void destroyStatics()
195
    {
196
    mPrograms.clear();
197
    mSources.clear();
198
    mNumSources = 0;
199
200
    Method method=null;
201
202
    for(EffectName name: EffectName.values())
203
      {
204
      if( name.getType() == EffectType.POSTPROCESS )
205
        {
206
        Class<? extends Effect> cls = name.getEffectClass();
207
208
        try
209
          {
210
          method = cls.getMethod("destroyStatics");
211
          }
212
        catch(NoSuchMethodException ex)
213
          {
214
          android.util.Log.e("postprocess", "exception getting method: "+ex.getMessage());
215
          }
216
217
        try
218
          {
219
          method.invoke(null);
220
          }
221
        catch(Exception ex)
222
          {
223
          android.util.Log.e("postprocess", "exception invoking method: "+ex.getMessage());
224
          }
225
        }
226
      }
227
    }
228
229 b547aaba leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
230
231 a0d5e302 Leszek Koltunski
  PostprocessEffect(EffectName name)
232 b547aaba leszek
    {
233 9d0d8530 leszek
    super(name);
234 86d322b5 Leszek Koltunski
235
    mQualityLevel = 0;
236
    mQualityScale = 1.0f;
237
    }
238
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
// PUBLIC API
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
/**
243
 * The higher the quality, the better the effect will look like and the slower it will be.
244
 * <p>
245
 * This works by rendering into smaller and smaller intermediate buffers. Each step renders into a
246
 * buffer that's half the size of the previous one.
247
 * <p>
248
 * We cannot this during mid-render - thus, give it to the Master to assign us back this job on the
249
 * next render.
250
 */
251
  public void setQuality(EffectQuality quality)
252
    {
253
    mJobs.add(new Job(MIPMAP,quality.getLevel()));
254
    DistortedMaster.newSlave(this);
255 b547aaba leszek
    }
256 8eccf334 Leszek Koltunski
  }