Project

General

Profile

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

library / src / main / java / org / distorted / library / effect / PostprocessEffect.java @ 96e3b88a

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
import org.distorted.library.main.DistortedFramebuffer;
23
import org.distorted.library.main.InternalMaster;
24
import org.distorted.library.program.DistortedProgram;
25

    
26
import java.lang.reflect.Method;
27
import java.nio.ByteBuffer;
28
import java.nio.ByteOrder;
29
import java.nio.FloatBuffer;
30
import java.util.ArrayList;
31

    
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33
/**
34
 * Abstract class that represents an Effect that works by running a certain Shader Program(s) on a Framebuffer.
35
 */
36
public abstract class PostprocessEffect extends Effect implements InternalMaster.Slave
37
  {
38
  private static final int MIPMAP = 0;
39
  /**
40
   * 5 per-effect interpolated values.
41
   */
42
  public static final int NUM_FLOAT_UNIFORMS = 6;
43
  /**
44
   * 1: the name of the effect
45
   */
46
  public static final int NUM_INT_UNIFORMS = 1;
47

    
48
  static final int POS_DATA_SIZE= 2;
49
  static final int TEX_DATA_SIZE= 2;
50

    
51
  static final FloatBuffer mQuadPositions, mQuadTexture, mQuadTextureInv;
52

    
53
  static
54
    {
55
    int dataLength      = 4;
56
    int bytes_per_float = 4;
57

    
58
    float[] position  = { -0.5f, -0.5f,  -0.5f, 0.5f,  0.5f,-0.5f,  0.5f, 0.5f };
59
    float[] textureNor= {  0.0f,  0.0f,   0.0f, 1.0f,  1.0f, 0.0f,  1.0f, 1.0f };
60
    float[] textureInv= {  0.0f,  0.0f,   1.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f };
61

    
62
    mQuadPositions = ByteBuffer.allocateDirect(POS_DATA_SIZE*dataLength*bytes_per_float).order(ByteOrder.nativeOrder()).asFloatBuffer();
63
    mQuadPositions.put(position).position(0);
64
    mQuadTexture   = ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*bytes_per_float).order(ByteOrder.nativeOrder()).asFloatBuffer();
65
    mQuadTexture.put(textureNor).position(0);
66
    mQuadTextureInv= ByteBuffer.allocateDirect(TEX_DATA_SIZE*dataLength*bytes_per_float).order(ByteOrder.nativeOrder()).asFloatBuffer();
67
    mQuadTextureInv.put(textureInv).position(0);
68
    }
69

    
70
  private static class Source
71
    {
72
    private String mName, mVertexShader, mFragmentShader;
73

    
74
    Source(String name, String vertex, String fragment)
75
      {
76
      mName           = name;
77
      mVertexShader   = vertex;
78
      mFragmentShader = fragment;
79
      }
80
    }
81

    
82
  static ArrayList<DistortedProgram> mPrograms = new ArrayList<>();
83
  private static ArrayList<Source> mSources = new ArrayList<>();
84
  private static int mNumSources = 0;
85

    
86
  private static class Job
87
    {
88
    int type;
89
    int level;
90

    
91
    Job(int t, int l)
92
      {
93
      type = t;
94
      level= l;
95
      }
96
    }
97

    
98
  private ArrayList<Job> mJobs = new ArrayList<>();
99
  private int mQualityLevel;
100

    
101
  float mQualityScale;
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  static int register(final String name, final String vertexShader, final String fragmentShader)
106
    {
107
    mSources.add(new Source(name,vertexShader,fragmentShader));
108

    
109
    return mNumSources++;
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
/**
114
 * Only for use by the library itself.
115
 *
116
 * @y.exclude
117
 */
118
  public static void createPrograms(int GLSL)
119
    {
120
    Source source;
121
    int len = mSources.size();
122

    
123
    String version = "#version "+GLSL+" es\n";
124

    
125
    for(int i=0; i<len; i++)
126
      {
127
      source = mSources.remove(0);
128

    
129
      try
130
        {
131
        mPrograms.add (new DistortedProgram(version+source.mVertexShader,version+source.mFragmentShader));
132
        }
133
      catch(Exception e)
134
        {
135
        android.util.Log.e("Effects", "exception trying to compile "+source.mName+" program: "+e.getMessage());
136
        throw new RuntimeException(e.getMessage());
137
        }
138
      }
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142
/**
143
 * Only for use by the library itself.
144
 *
145
 * @y.exclude
146
 */
147
  public abstract int apply(float[] uniforms, int index, DistortedFramebuffer buffer);
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
  /**
151
   * Only for use by the library itself.
152
   *
153
   * @y.exclude
154
   */
155
  public abstract boolean getRender();
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
  /**
159
   * Only for use by the library itself.
160
   *
161
   * @y.exclude
162
   */
163
  public int getQuality()
164
    {
165
    return mQualityLevel;
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169
/**
170
 * This is not really part of the public API. Has to be public only because it is a part of the
171
 * DistortedSlave interface, which should really be a class that we extend here instead but
172
 * Java has no multiple inheritance.
173
 *
174
 * @y.exclude
175
 */
176
  public void doWork()
177
    {
178
    int num = mJobs.size();
179
    Job job;
180

    
181
    for(int i=0; i<num; i++)
182
      {
183
      job = mJobs.remove(0);
184

    
185
      switch(job.type)
186
        {
187
        case MIPMAP: int level = job.level;
188
                     mQualityLevel = level;
189
                     mQualityScale = 1.0f;
190
                     for(int j=0; j<level; j++) mQualityScale*= EffectQuality.MULTIPLIER;
191
                     break;
192
        }
193
      }
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  static void destroyStatics()
199
    {
200
    mPrograms.clear();
201
    mSources.clear();
202
    mNumSources = 0;
203

    
204
    Method method;
205

    
206
    for(EffectName name: EffectName.values())
207
      {
208
      if( name.getType() == EffectType.POSTPROCESS )
209
        {
210
        Class<? extends Effect> cls = name.getEffectClass();
211

    
212
        try
213
          {
214
          method = cls.getDeclaredMethod("destroyStatics");  // destroyStatics not public, thus getDeclaredMethod
215
          }
216
        catch(NoSuchMethodException ex)
217
          {
218
          android.util.Log.e("postprocess", cls.getSimpleName()+": exception getting method: "+ex.getMessage());
219
          method = null;
220
          }
221

    
222
        try
223
          {
224
          if( method!=null ) method.invoke(null);
225
          }
226
        catch(Exception ex)
227
          {
228
          android.util.Log.e("postprocess", "exception invoking method: "+ex.getMessage());
229
          }
230
        }
231
      }
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  PostprocessEffect(EffectName name)
237
    {
238
    super(name);
239

    
240
    mQualityLevel = 0;
241
    mQualityScale = 1.0f;
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
// PUBLIC API
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
/**
248
 * The higher the quality, the better the effect will look like and the slower it will be.
249
 * <p>
250
 * This works by rendering into smaller and smaller intermediate buffers. Each step renders into a
251
 * buffer that's half the size of the previous one.
252
 * <p>
253
 * We cannot this during mid-render - thus, give it to the Master to assign us back this job on the
254
 * next render.
255
 */
256
  public void setQuality(EffectQuality quality)
257
    {
258
    mJobs.add(new Job(MIPMAP,quality.getLevel()));
259
    InternalMaster.newSlave(this);
260
    }
261
  }
(17-17/32)