Revision d6e94c84
Added by Leszek Koltunski almost 8 years ago
src/main/java/org/distorted/library/Distorted.java | ||
---|---|---|
20 | 20 |
package org.distorted.library; |
21 | 21 |
|
22 | 22 |
import android.content.Context; |
23 |
import android.content.res.Resources; |
|
23 | 24 |
import android.opengl.GLES20; |
24 | 25 |
import org.distorted.library.program.*; |
25 | 26 |
|
... | ... | |
62 | 63 |
* This way we can have two different DistortedEffects sharing the FRAGMENT queue. |
63 | 64 |
*/ |
64 | 65 |
public static final int CLONE_FRAGMENT= 0x8; |
66 |
/** |
|
67 |
* When creating an instance of a DistortedEffects from another instance, clone the PostProcess Effects. |
|
68 |
* <p> |
|
69 |
* This way we can have two different DistortedEffects sharing the POSTPROCESS queue. |
|
70 |
*/ |
|
71 |
public static final int CLONE_POSTPROCESS= 0x10; |
|
65 | 72 |
/** |
66 | 73 |
* When creating an instance of a DistortedTree from another instance, clone the children Nodes. |
67 | 74 |
* <p> |
68 | 75 |
* This is mainly useful for creating many similar sub-trees and rendering then at different places |
69 | 76 |
* on the screen with (optionally) different Effects. |
70 | 77 |
*/ |
71 |
public static final int CLONE_CHILDREN= 0x10;
|
|
78 |
public static final int CLONE_CHILDREN= 0x20;
|
|
72 | 79 |
|
73 | 80 |
static int[] mMainProgramAttributes; |
81 |
static int[] mPostProgramAttributes; |
|
82 |
|
|
83 |
static int mainProgramH, postProgramH; |
|
74 | 84 |
|
75 | 85 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
76 | 86 |
|
... | ... | |
102 | 112 |
*/ |
103 | 113 |
public static void onCreate(final Context context) |
104 | 114 |
throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException |
105 |
{ |
|
106 |
final InputStream vertexStream = context.getResources().openRawResource(R.raw.main_vertex_shader); |
|
107 |
final InputStream fragmentStream = context.getResources().openRawResource(R.raw.main_fragment_shader); |
|
115 |
{ |
|
116 |
final Resources resources = context.getResources(); |
|
108 | 117 |
|
109 |
DistortedProgram mainProgram = new DistortedProgram(vertexStream,fragmentStream); |
|
110 |
int programH = mainProgram.getProgramHandle(); |
|
111 |
GLES20.glUseProgram(programH); |
|
118 |
final InputStream mainVertexStream = resources.openRawResource(R.raw.main_vertex_shader); |
|
119 |
final InputStream mainFragmentStream = resources.openRawResource(R.raw.main_fragment_shader); |
|
120 |
|
|
121 |
DistortedProgram mainProgram = new DistortedProgram(mainVertexStream,mainFragmentStream); |
|
122 |
mainProgramH = mainProgram.getProgramHandle(); |
|
123 |
GLES20.glUseProgram(mainProgramH); |
|
112 | 124 |
mainProgram.bindAndEnableAttributes(); |
113 | 125 |
mMainProgramAttributes = mainProgram.getAttributes(); |
114 | 126 |
|
... | ... | |
119 | 131 |
GLES20.glCullFace(GLES20.GL_BACK); |
120 | 132 |
GLES20.glFrontFace(GLES20.GL_CW); |
121 | 133 |
|
122 |
EffectQueueFragment.getUniforms(programH); |
|
123 |
EffectQueueVertex.getUniforms(programH); |
|
124 |
EffectQueueMatrix.getUniforms(programH); |
|
125 |
DistortedTexture.getUniforms(programH); |
|
134 |
EffectQueueFragment.getUniforms(mainProgramH); |
|
135 |
EffectQueueVertex.getUniforms(mainProgramH); |
|
136 |
EffectQueueMatrix.getUniforms(mainProgramH); |
|
137 |
DistortedTexture.getUniforms(mainProgramH); |
|
138 |
|
|
139 |
final InputStream postVertexStream = resources.openRawResource(R.raw.post_vertex_shader); |
|
140 |
final InputStream postFragmentStream = resources.openRawResource(R.raw.post_fragment_shader); |
|
141 |
|
|
142 |
DistortedProgram postProgram = new DistortedProgram(postVertexStream,postFragmentStream); |
|
143 |
postProgramH = postProgram.getProgramHandle(); |
|
144 |
GLES20.glUseProgram(postProgramH); |
|
145 |
postProgram.bindAndEnableAttributes(); |
|
146 |
mPostProgramAttributes = postProgram.getAttributes(); |
|
147 |
|
|
148 |
EffectQueuePostprocess.getUniforms(postProgramH); |
|
126 | 149 |
|
127 | 150 |
DistortedTree.reset(); |
128 | 151 |
EffectMessageSender.startSending(); |
src/main/java/org/distorted/library/DistortedEffects.java | ||
---|---|---|
40 | 40 |
private static long mNextID =0; |
41 | 41 |
private long mID; |
42 | 42 |
|
43 |
private EffectQueueMatrix mM; |
|
44 |
private EffectQueueFragment mF; |
|
45 |
private EffectQueueVertex mV; |
|
43 |
private EffectQueueMatrix mM; |
|
44 |
private EffectQueueFragment mF; |
|
45 |
private EffectQueueVertex mV; |
|
46 |
private EffectQueuePostprocess mP; |
|
46 | 47 |
|
47 |
private boolean matrixCloned, vertexCloned, fragmentCloned; |
|
48 |
private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
|
|
48 | 49 |
|
49 | 50 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
50 | 51 |
|
... | ... | |
82 | 83 |
mF = new EffectQueueFragment(mID); |
83 | 84 |
fragmentCloned = false; |
84 | 85 |
} |
86 |
|
|
87 |
if( (flags & Distorted.CLONE_POSTPROCESS) != 0 ) |
|
88 |
{ |
|
89 |
mP = d.mP; |
|
90 |
postprocessCloned = true; |
|
91 |
} |
|
92 |
else |
|
93 |
{ |
|
94 |
mP = new EffectQueuePostprocess(mID); |
|
95 |
postprocessCloned = false; |
|
96 |
} |
|
85 | 97 |
} |
86 | 98 |
|
87 | 99 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
88 | 100 |
|
89 | 101 |
void drawPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df, long currTime) |
90 | 102 |
{ |
91 |
GLES20.glViewport(0, 0, df.mWidth, df.mHeight); |
|
92 |
|
|
93 |
float halfZ = halfInputW*mesh.zFactor; |
|
94 |
|
|
95 | 103 |
mM.compute(currTime); |
96 |
mM.send(df,halfInputW,halfInputH,halfZ); |
|
97 |
|
|
98 | 104 |
mV.compute(currTime); |
99 |
mV.send(halfInputW,halfInputH,halfZ); |
|
100 |
|
|
101 | 105 |
mF.compute(currTime); |
102 |
mF.send(halfInputW,halfInputH);
|
|
106 |
mP.compute(currTime);
|
|
103 | 107 |
|
104 |
mesh.draw(); |
|
108 |
float halfZ = halfInputW*mesh.zFactor; |
|
109 |
|
|
110 |
GLES20.glUseProgram(Distorted.mainProgramH); |
|
111 |
|
|
112 |
if( mP.mNumEffects==0 ) |
|
113 |
{ |
|
114 |
GLES20.glViewport(0, 0, df.mWidth, df.mHeight); |
|
115 |
|
|
116 |
mM.send(df,halfInputW,halfInputH,halfZ); |
|
117 |
mV.send(halfInputW,halfInputH,halfZ); |
|
118 |
mF.send(halfInputW,halfInputH); |
|
119 |
|
|
120 |
mesh.draw(); |
|
121 |
} |
|
122 |
else |
|
123 |
{ |
|
124 |
DistortedFramebuffer fbo = null; |
|
125 |
// TODO : set this as output |
|
126 |
|
|
127 |
// render to the FBO just like above |
|
128 |
/* |
|
129 |
GLES20.glViewport(0, 0, fbo.mWidth, fbo.mHeight); |
|
130 |
|
|
131 |
mM.send(fbo,halfInputW,halfInputH,halfZ); |
|
132 |
mV.send(halfInputW,halfInputH,halfZ); |
|
133 |
mF.send(halfInputW,halfInputH); |
|
134 |
|
|
135 |
mesh.draw(); |
|
136 |
*/ |
|
137 |
|
|
138 |
GLES20.glUseProgram(Distorted.postProgramH); |
|
139 |
|
|
140 |
// apply postprocess effects |
|
141 |
mP.postprocess(fbo,df); |
|
142 |
} |
|
105 | 143 |
} |
106 | 144 |
|
107 | 145 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
108 | 146 |
|
109 |
void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df) |
|
147 |
static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df)
|
|
110 | 148 |
{ |
111 | 149 |
GLES20.glViewport(0, 0, df.mWidth, df.mHeight); |
112 | 150 |
|
113 |
mM.sendZero(df,halfInputW,halfInputH,halfInputW*mesh.zFactor); |
|
114 |
mV.sendZero(); |
|
115 |
mF.sendZero(); |
|
151 |
EffectQueueMatrix.sendZero(df,halfInputW,halfInputH,halfInputW*mesh.zFactor); |
|
152 |
EffectQueueVertex.sendZero(); |
|
153 |
EffectQueueFragment.sendZero(); |
|
154 |
EffectQueuePostprocess.sendZero(2*halfInputW,2*halfInputH); |
|
116 | 155 |
|
117 | 156 |
mesh.draw(); |
118 | 157 |
} |
... | ... | |
121 | 160 |
|
122 | 161 |
private void releasePriv() |
123 | 162 |
{ |
124 |
if( !matrixCloned ) mM.abortAll(false); |
|
125 |
if( !vertexCloned ) mV.abortAll(false); |
|
126 |
if( !fragmentCloned) mF.abortAll(false); |
|
163 |
if( !matrixCloned ) mM.abortAll(false); |
|
164 |
if( !vertexCloned ) mV.abortAll(false); |
|
165 |
if( !fragmentCloned ) mF.abortAll(false); |
|
166 |
if( !postprocessCloned) mP.abortAll(false); |
|
127 | 167 |
|
128 | 168 |
mM = null; |
129 | 169 |
mV = null; |
130 | 170 |
mF = null; |
171 |
mP = null; |
|
131 | 172 |
} |
132 | 173 |
|
133 | 174 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
197 | 238 |
mV.registerForMessages(el); |
198 | 239 |
mF.registerForMessages(el); |
199 | 240 |
mM.registerForMessages(el); |
241 |
mP.registerForMessages(el); |
|
200 | 242 |
} |
201 | 243 |
|
202 | 244 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
210 | 252 |
mV.deregisterForMessages(el); |
211 | 253 |
mF.deregisterForMessages(el); |
212 | 254 |
mM.deregisterForMessages(el); |
255 |
mP.deregisterForMessages(el); |
|
213 | 256 |
} |
214 | 257 |
|
215 | 258 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
219 | 262 |
*/ |
220 | 263 |
public int abortAllEffects() |
221 | 264 |
{ |
222 |
return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true); |
|
265 |
return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true) + mP.abortAll(true);
|
|
223 | 266 |
} |
224 | 267 |
|
225 | 268 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
233 | 276 |
{ |
234 | 277 |
switch(type) |
235 | 278 |
{ |
236 |
case MATRIX : return mM.abortAll(true); |
|
237 |
case VERTEX : return mV.abortAll(true); |
|
238 |
case FRAGMENT: return mF.abortAll(true); |
|
239 |
default : return 0; |
|
279 |
case MATRIX : return mM.abortAll(true); |
|
280 |
case VERTEX : return mV.abortAll(true); |
|
281 |
case FRAGMENT : return mF.abortAll(true); |
|
282 |
case POSTPROCESS: return mP.abortAll(true); |
|
283 |
default : return 0; |
|
240 | 284 |
} |
241 | 285 |
} |
242 | 286 |
|
... | ... | |
251 | 295 |
{ |
252 | 296 |
int type = (int)(id&EffectTypes.MASK); |
253 | 297 |
|
254 |
if( type==EffectTypes.MATRIX.type ) return mM.removeByID(id>>EffectTypes.LENGTH); |
|
255 |
if( type==EffectTypes.VERTEX.type ) return mV.removeByID(id>>EffectTypes.LENGTH); |
|
256 |
if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH); |
|
298 |
if( type==EffectTypes.MATRIX.type ) return mM.removeByID(id>>EffectTypes.LENGTH); |
|
299 |
if( type==EffectTypes.VERTEX.type ) return mV.removeByID(id>>EffectTypes.LENGTH); |
|
300 |
if( type==EffectTypes.FRAGMENT.type ) return mF.removeByID(id>>EffectTypes.LENGTH); |
|
301 |
if( type==EffectTypes.POSTPROCESS.type ) return mP.removeByID(id>>EffectTypes.LENGTH); |
|
257 | 302 |
|
258 | 303 |
return 0; |
259 | 304 |
} |
... | ... | |
269 | 314 |
{ |
270 | 315 |
switch(name.getType()) |
271 | 316 |
{ |
272 |
case MATRIX : return mM.removeByType(name); |
|
273 |
case VERTEX : return mV.removeByType(name); |
|
274 |
case FRAGMENT: return mF.removeByType(name); |
|
275 |
default : return 0; |
|
317 |
case MATRIX : return mM.removeByType(name); |
|
318 |
case VERTEX : return mV.removeByType(name); |
|
319 |
case FRAGMENT : return mF.removeByType(name); |
|
320 |
case POSTPROCESS: return mP.removeByType(name); |
|
321 |
default : return 0; |
|
276 | 322 |
} |
277 | 323 |
} |
278 | 324 |
|
... | ... | |
288 | 334 |
{ |
289 | 335 |
int type = (int)(id&EffectTypes.MASK); |
290 | 336 |
|
291 |
if( type==EffectTypes.MATRIX.type ) return mM.printByID(id>>EffectTypes.LENGTH); |
|
292 |
if( type==EffectTypes.VERTEX.type ) return mV.printByID(id>>EffectTypes.LENGTH); |
|
293 |
if( type==EffectTypes.FRAGMENT.type ) return mF.printByID(id>>EffectTypes.LENGTH); |
|
337 |
if( type==EffectTypes.MATRIX.type ) return mM.printByID(id>>EffectTypes.LENGTH); |
|
338 |
if( type==EffectTypes.VERTEX.type ) return mV.printByID(id>>EffectTypes.LENGTH); |
|
339 |
if( type==EffectTypes.FRAGMENT.type ) return mF.printByID(id>>EffectTypes.LENGTH); |
|
340 |
if( type==EffectTypes.POSTPROCESS.type ) return mP.printByID(id>>EffectTypes.LENGTH); |
|
294 | 341 |
|
295 | 342 |
return false; |
296 | 343 |
} |
... | ... | |
864 | 911 |
{ |
865 | 912 |
return mV.add(EffectNames.WAVE, wave, center, region); |
866 | 913 |
} |
914 |
|
|
915 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
916 |
// Postprocess-based effects |
|
917 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
918 |
/** |
|
919 |
* Blur the object. |
|
920 |
* |
|
921 |
* @param radius The 'strength' if the effect, in pixels. 0 = no blur, 10 = when blurring a given pixel, |
|
922 |
* take into account 10 pixels in each direction. |
|
923 |
* @param center 2-dimensional Data that, at any given time, returns the Center of the Effect. |
|
924 |
* @return ID of the effect added, or -1 if we failed to add one. |
|
925 |
*/ |
|
926 |
public long blur(Data1D radius, Data2D center) |
|
927 |
{ |
|
928 |
return mP.add(EffectNames.BLUR, radius, center); |
|
929 |
} |
|
867 | 930 |
} |
src/main/java/org/distorted/library/DistortedFramebuffer.java | ||
---|---|---|
243 | 243 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
244 | 244 |
// must be called form a thread holding OpenGL Context |
245 | 245 |
|
246 |
static synchronized void deleteAllMarked() |
|
246 |
private static synchronized void deleteAllMarked()
|
|
247 | 247 |
{ |
248 | 248 |
if( mListMarked ) |
249 | 249 |
{ |
src/main/java/org/distorted/library/DistortedTree.java | ||
---|---|---|
222 | 222 |
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); |
223 | 223 |
|
224 | 224 |
if( mTexture.setAsInput() ) |
225 |
mEffects.drawNoEffectsPriv(mTexture.mHalfX, mTexture.mHalfY, mMesh, mData.mFBO);
|
|
225 |
DistortedEffects.drawNoEffectsPriv(mTexture.mHalfX, mTexture.mHalfY, mMesh, mData.mFBO);
|
|
226 | 226 |
|
227 | 227 |
synchronized(this) |
228 | 228 |
{ |
src/main/java/org/distorted/library/EffectQueueFragment.java | ||
---|---|---|
134 | 134 |
|
135 | 135 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
136 | 136 |
|
137 |
synchronized void sendZero()
|
|
137 |
synchronized static void sendZero()
|
|
138 | 138 |
{ |
139 | 139 |
GLES20.glUniform1i( mNumEffectsH, 0); |
140 | 140 |
} |
src/main/java/org/distorted/library/EffectQueueMatrix.java | ||
---|---|---|
257 | 257 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
258 | 258 |
// here construct the ModelView Matrix, but without any effects |
259 | 259 |
|
260 |
synchronized void sendZero(DistortedFramebuffer df, float halfX, float halfY, float halfZ) |
|
260 |
synchronized static void sendZero(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
|
|
261 | 261 |
{ |
262 | 262 |
Matrix.setIdentityM(mTmpMatrix, 0); |
263 | 263 |
Matrix.translateM(mTmpMatrix, 0, halfX-df.mWidth/2, df.mHeight/2-halfY, -df.mDistance); |
src/main/java/org/distorted/library/EffectQueuePostprocess.java | ||
---|---|---|
98 | 98 |
mTime = currTime; |
99 | 99 |
} |
100 | 100 |
|
101 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
102 |
|
|
103 |
void postprocess(DistortedFramebuffer input, DistortedFramebuffer output) |
|
104 |
{ |
|
105 |
// TODO |
|
106 |
} |
|
107 |
|
|
101 | 108 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
102 | 109 |
|
103 | 110 |
protected void moveEffect(int index) |
... | ... | |
121 | 128 |
} |
122 | 129 |
} |
123 | 130 |
|
131 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
132 |
|
|
133 |
synchronized static void sendZero(float objX, float objY) |
|
134 |
{ |
|
135 |
GLES20.glUniform1i( mNumEffectsH, 0); |
|
136 |
GLES20.glUniform2f( mObjDH , objX, objY); |
|
137 |
} |
|
138 |
|
|
124 | 139 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
125 | 140 |
// blur |
126 | 141 |
|
src/main/java/org/distorted/library/EffectQueueVertex.java | ||
---|---|---|
153 | 153 |
|
154 | 154 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
155 | 155 |
|
156 |
synchronized void sendZero()
|
|
156 |
synchronized static void sendZero()
|
|
157 | 157 |
{ |
158 | 158 |
GLES20.glUniform1i( mNumEffectsH, 0); |
159 | 159 |
} |
src/main/res/raw/post_fragment_shader.glsl | ||
---|---|---|
17 | 17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
18 | 18 |
////////////////////////////////////////////////////////////////////////////////////////////// |
19 | 19 |
|
20 |
varying vec2 vTexCoordinate; |
|
20 |
#define NUM_POSTPROCESS 3 |
|
21 |
#define BLUR 0 |
|
22 |
|
|
23 |
precision lowp float; |
|
24 |
|
|
25 |
varying vec2 v_TexCoordinate; |
|
21 | 26 |
uniform sampler2D u_Texture; |
22 | 27 |
uniform vec2 u_objD; |
23 |
uniform int fNumEffects; // total number of postprocessing effects
|
|
28 |
uniform int pNumEffects; // total number of postprocessing effects
|
|
24 | 29 |
|
25 | 30 |
#if NUM_POSTPROCESS>0 |
26 | 31 |
uniform int pType[NUM_POSTPROCESS]; // their types. |
27 | 32 |
uniform vec4 pUniforms[2*NUM_POSTPROCESS]; // i-th effect is 2 consecutive vec4's: [2*i], [2*i+1]. |
28 |
// |
|
29 | 33 |
|
30 | 34 |
////////////////////////////////////////////////////////////////////////////////////////////// |
31 | 35 |
// BLUR EFFECT |
32 | 36 |
|
33 |
void blur(out vec4 color)
|
|
37 |
void blur(out vec4 pixel)
|
|
34 | 38 |
{ |
35 |
color = vec4(0.0);
|
|
39 |
pixel = vec4(0.0);
|
|
36 | 40 |
|
37 | 41 |
float blurSizeH = 1.0 / u_objD.x; |
38 | 42 |
float blurSizeV = 1.0 / u_objD.y; |
39 | 43 |
|
40 |
for (int x = -4; x <= 4; x++) |
|
41 |
for (int y = -4; y <= 4; y++) |
|
42 |
color += texture( u_Texture, vec2(vTexCoord.x + x * blurSizeH, vTexCoord.y + y * blurSizeV) ) / 81.0; |
|
44 |
for (float x = -4.0; x <= 4.0; x+=1.0) |
|
45 |
for (float y = -4.0; y <= 4.0; y+=1.0) |
|
46 |
{ |
|
47 |
pixel += texture2D( u_Texture, vec2(v_TexCoordinate.x + x * blurSizeH, v_TexCoordinate.y + y * blurSizeV) ) / 81.0; |
|
48 |
} |
|
43 | 49 |
} |
44 | 50 |
|
45 | 51 |
#endif |
... | ... | |
51 | 57 |
vec4 pixel = texture2D(u_Texture,v_TexCoordinate); |
52 | 58 |
|
53 | 59 |
#if NUM_POSTPROCESS>0 |
54 |
for(int i=0; i<fNumEffects; i++)
|
|
60 |
for(int i=0; i<pNumEffects; i++)
|
|
55 | 61 |
{ |
56 | 62 |
if( pType[i]==BLUR ) blur(pixel); |
57 | 63 |
} |
Also available in: Unified diff
progress with Postprocessing.