@@ -3,6 +3,7 @@ package com.oussama.portfolio.ui.components.glimageview
3
3
import android.animation.Animator
4
4
import android.animation.AnimatorSet
5
5
import android.animation.ValueAnimator
6
+ import android.content.Context
6
7
import android.graphics.Bitmap
7
8
import android.graphics.Color
8
9
import android.opengl.GLES20
@@ -11,7 +12,10 @@ import android.opengl.GLUtils
11
12
import android.opengl.Matrix
12
13
import android.view.MotionEvent
13
14
import android.view.animation.AnticipateOvershootInterpolator
15
+ import com.oussama.portfolio.BaseApplication
14
16
import timber.log.Timber
17
+ import java.io.BufferedReader
18
+ import java.io.InputStreamReader
15
19
import java.nio.ByteBuffer
16
20
import java.nio.ByteOrder
17
21
import java.nio.FloatBuffer
@@ -166,6 +170,32 @@ class ImageRenderer(
166
170
fun paused (isPaused : Boolean ) {
167
171
this .isPaused = isPaused
168
172
}
173
+
174
+ companion object {
175
+ @JvmStatic
176
+ fun loadFromAsset (context : Context , fileName : String ): String {
177
+ val assetManager = context.assets
178
+ try {
179
+ val inputStream = assetManager.open(fileName)
180
+ val bufferedReader = BufferedReader (InputStreamReader (inputStream))
181
+ val stringBuilder = StringBuilder ()
182
+ var line: String?
183
+ do {
184
+ line = bufferedReader.readLine()
185
+ if (line != null ) {
186
+ stringBuilder.append(line)
187
+ stringBuilder.append(" \n " )
188
+ }
189
+ } while (line != null )
190
+ bufferedReader.close()
191
+ inputStream.close()
192
+ return stringBuilder.toString()
193
+ } catch (e: Exception ) {
194
+ e.printStackTrace()
195
+ return " "
196
+ }
197
+ }
198
+ }
169
199
}
170
200
171
201
class Square (bitmap : Bitmap ) {
@@ -213,165 +243,9 @@ class Square(bitmap: Bitmap) {
213
243
private var rangeSkippingValue = maxRangeSkippingValue
214
244
215
245
init {
216
- val vertexShaderCode =
217
- " uniform mat4 uMVPMatrix;\n " +
218
- " attribute vec2 vPosition;\n " +
219
- " attribute vec2 aTextureCoord;\n " +
220
- " \n " +
221
- " void main() {\n " +
222
- " gl_Position = vec4(vPosition, 0, 1);\n " +
223
- " }"
224
-
225
- val fragmentShaderCode =
226
- " precision mediump float;\n " +
227
- " \n " +
228
- " uniform vec2 u_resolution;\n " +
229
- " uniform int isTouching;\n " +
230
- " uniform sampler2D u_texture0;\n " +
231
- " uniform float startRangeX; \n " +
232
- " uniform float endRangeX; \n " +
233
- " uniform float startRangeY; \n " +
234
- " uniform float endRangeY; \n " +
235
- " uniform float initialAlpha; \n " +
236
- " uniform float rangeSkippingValue; \n " +
237
- " \n " +
238
- " float character(float n, vec2 p)\n " +
239
- " {\n " +
240
- " p = floor(p*vec2(4.0, -4.0) + 2.5);\n " +
241
- " if (clamp(p.x, 0.0, 4.0) == p.x)\n " +
242
- " {\n " +
243
- " if (clamp(p.y, 0.0, 4.0) == p.y)\n " +
244
- " {\n " +
245
- " if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0;\n " +
246
- " }\n " +
247
- " }\n " +
248
- " return 0.0;\n " +
249
- " }\n " +
250
- " vec3 invertColor(vec3 color) {\n " +
251
- " return vec3(1.0 - color.r, 1.0 - color.g, 1.0 - color.b);\n " +
252
- " }\n " +
253
- " \n " +
254
- " bool isBlack(vec3 color) {\n " +
255
- " return color.r == 0.0 && color.g == 0.0 && color.b == 0.0;\n " +
256
- " }\n " +
257
- " bool isInsideRange(vec2 uv, float startRangeX, float endRangeX, float startRangeY, float endRangeY, vec2 u_resolution, float rangeModifier) { // Checks if is inside a square \n " +
258
- " float scaledStartRangeX = startRangeX + rangeModifier;\n " +
259
- " float scaledEndRangeX = endRangeX - rangeModifier;\n " +
260
- " float scaledStartRangeY = startRangeY + rangeModifier;\n " +
261
- " float scaledEndRangeY = endRangeY - rangeModifier;\n " +
262
- " \n " +
263
- " return (uv.x > scaledStartRangeX / u_resolution.x && uv.x < scaledEndRangeX / u_resolution.x &&\n " +
264
- " uv.y > scaledStartRangeY / u_resolution.y && uv.y < scaledEndRangeY / u_resolution.y);\n " +
265
- " }\n " +
266
- " bool isInsideCircle(vec2 uv, vec2 center, float radius, vec2 u_resolution) {\n " +
267
- " vec2 normalizedUV = uv * u_resolution / max(u_resolution.x, u_resolution.y);\n " +
268
- " vec2 normalizedCenter = center / max(u_resolution.x, u_resolution.y);\n " +
269
- " float distanceSquared = dot(normalizedUV - normalizedCenter, normalizedUV - normalizedCenter);\n " +
270
- " float radiusSquared = (radius / max(u_resolution.x, u_resolution.y)) * (radius / max(u_resolution.x, u_resolution.y));\n " +
271
- " return distanceSquared < radiusSquared;\n " +
272
- " }" +
273
- " float calculateAlphaFalloff(vec2 uv, vec2 u_resolution) {\n " +
274
- " float distToLeft = uv.x;\n " +
275
- " float distToRight = u_resolution.x - uv.x;\n " +
276
- " float distToTop = uv.y;\n " +
277
- " float distToBottom = u_resolution.y - uv.y;\n " +
278
- " \n " +
279
- " float edgeThreshold = 0.2; // Adjust the edge threshold here\n " +
280
- " \n " +
281
- " // Normalize distances\n " +
282
- " float maxDist = max(u_resolution.x, u_resolution.y);\n " +
283
- " distToLeft /= maxDist;\n " +
284
- " distToRight /= maxDist;\n " +
285
- " distToTop /= maxDist;\n " +
286
- " distToBottom /= maxDist;\n " +
287
- " \n " +
288
- " float alpha = initialAlpha;\n " +
289
- " \n " +
290
- " // Check if the pixel is closer to the left or right side\n " +
291
- " float minHorizontalDist = min(distToLeft, distToRight);\n " +
292
- " alpha *= smoothstep(0.0, edgeThreshold, minHorizontalDist);\n " +
293
- " \n " +
294
- " // Check if the pixel is closer to the top or bottom side\n " +
295
- " float minVerticalDist = min(distToTop, distToBottom);\n " +
296
- " alpha *= smoothstep(0.0, edgeThreshold, minVerticalDist);\n " +
297
- " \n " +
298
- " return alpha;\n " +
299
- " }\n " +
300
- " void main() {\n " +
301
- " vec2 pix = gl_FragCoord.xy;\n " +
302
- " vec2 uv = pix / u_resolution.xy;\n " +
303
- " uv.y = 1.0 - uv.y; // Flip the texture vertically\n " +
304
- " \n " +
305
- " vec3 col = texture2D(u_texture0, uv).rgb;\n " +
306
- " float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;\n " +
307
- " \n " +
308
- " int n = 4096;\n " +
309
- " \n " +
310
- " // limited character set\n " +
311
- " if (gray > 0.2) n = 65600; // :\n " +
312
- " if (gray > 0.3) n = 163153; // *\n " +
313
- " if (gray > 0.4) n = 15255086; // o \n " +
314
- " if (gray > 0.5) n = 13121101; // &\n " +
315
- " if (gray > 0.6) n = 15252014; // 8\n " +
316
- " if (gray > 0.7) n = 13195790; // @\n " +
317
- " if (gray > 0.8) n = 11512810; // #\n " +
318
- " \n " +
319
- " float charsize = 4.8;\n " +
320
- " float alpha = 1.0;\n " +
321
- " vec2 p = mod(pix / charsize, charsize / 2.0) - vec2(charsize / 4.0);\n " +
322
- " \n " +
323
- " float rangeModifier = endRangeY - startRangeY;\n " +
324
- " bool insideRange = isInsideCircle(uv, vec2((startRangeX + endRangeX) / 2.0, (startRangeY + endRangeY) / 2.0), (endRangeX - startRangeX) / 2.0, u_resolution);\n " +
325
- " \n " +
326
- " if (insideRange) {\n " +
327
- " vec2 center = vec2((startRangeX + endRangeX) / 2.0, (startRangeY + endRangeY) / 2.0);\n " +
328
- " float distance = distance(uv * u_resolution, center);\n " +
329
- " \n " +
330
-
331
- " \n " +
332
- " // Additional logic for changing characters gradually\n " +
333
- " float heatArea = clamp(1. - distance / (u_resolution.x * 0.5), 0.0, 1.0);\n " +
334
- " float bwFactor = 1.0;\n " +
335
- " float blenderDivider = (u_resolution.x * 0.1);\n " +
336
- " if (isTouching == 1) {\n " +
337
- " blenderDivider = (u_resolution.x * 0.22);\n " +
338
- " } else {\n " +
339
- " blenderDivider = (u_resolution.x * 0.11);" +
340
- " }" +
341
-
342
- " if (heatArea < 0.2) {\n " +
343
- " n = 4096;\n " +
344
- " } else if (heatArea < 0.3) {\n " +
345
- " n = 4096;\n " +
346
- " } else if (heatArea < 0.4) {\n " +
347
- " blenderDivider = (u_resolution.x * 0.45);" +
348
- " } else if (heatArea < 0.5) {\n " +
349
- " blenderDivider = (u_resolution.x * 0.4);" +
350
- " } else if (heatArea < 0.6) {\n " +
351
- " blenderDivider = (u_resolution.x * 0.4);" +
352
- " } \n " +
353
- " bwFactor = 1.2;\n " +
354
- " // Adjust the smoothstep range for a smoother blending\n " +
355
- " float blendAmount = smoothstep(0.1, 1.0, distance / blenderDivider);\n " +
356
- " \n " +
357
- " // Gradual blending from the center towards the edges\n " +
358
- " col = mix(col, vec3(character(float(n), p)), blendAmount);\n " +
359
- " if (heatArea < 0.2) {\n " +
360
- " col = vec3(character(float(n), p));\n " +
361
- " } else if (heatArea < rangeSkippingValue*0.9) {\n " +
362
- " col = (col * bwFactor) * character(float(n), p);\n " +
363
- " }\n " +
364
-
365
- " } else {\n " +
366
- " col = vec3(character(float(n), p));\n " +
367
- " }\n " +
368
- " \n " +
369
- " alpha = calculateAlphaFalloff(pix, u_resolution); " +
370
- " gl_FragColor = vec4(col, alpha);\n " +
371
- " }"
372
-
373
- val vertexShader = loadShader(GLES20 .GL_VERTEX_SHADER , vertexShaderCode)
374
- val fragmentShader = loadShader(GLES20 .GL_FRAGMENT_SHADER , fragmentShaderCode)
246
+
247
+ val vertexShader = loadShader(GLES20 .GL_VERTEX_SHADER , ImageRenderer .loadFromAsset(BaseApplication .INSTANCE , " shaders/vertex_shader.glsl" ))
248
+ val fragmentShader = loadShader(GLES20 .GL_FRAGMENT_SHADER , ImageRenderer .loadFromAsset(BaseApplication .INSTANCE , " shaders/fragment_shader.glsl" ))
375
249
376
250
program = GLES20 .glCreateProgram().also {
377
251
GLES20 .glAttachShader(it, vertexShader)
0 commit comments