diff --git a/content/profile/thanthtetaung.mdx b/content/profile/thanthtetaung.mdx
new file mode 100644
index 0000000..063819b
--- /dev/null
+++ b/content/profile/thanthtetaung.mdx
@@ -0,0 +1,17 @@
+---
+name: Thant Htet Aung
+description: I'm a creator more of a developer. Creating something out of nothing is something only God can do!
+image: "https://avatars.githubusercontent.com/u/114596700?v=4"
+tags:
+ - Fullstack
+ - Backend
+ - Laravel
+ - JavaScripts
+ - ReactJS
+ - Vue
+ - Bun
+---
+
+import App from '@/components/Contributors/Thant/App.jsx';
+
+
diff --git a/package.json b/package.json
index 1ebe558..ce33c63 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,11 @@
}
},
"dependencies": {
+ "@react-three/drei": "^9.88.7",
+ "@react-three/fiber": "^8.15.8",
+ "@react-three/postprocessing": "^2.15.8",
"@splinetool/react-spline": "^2.2.6",
+ "@types/three": "^0.158.0",
"clsx": "^2.0.0",
"commitlint": "^17.7.2",
"commitlint-config-gitmoji": "^2.3.1",
@@ -49,8 +53,9 @@
"remark-gfm": "^4.0.0",
"sass": "^1.69.4",
"shiki": "^0.14.5",
+ "suspend-react": "^0.1.3",
"tailwind-merge": "^1.14.0",
- "typed.js": "^2.0.16"
+ "three": "^0.158.0"
},
"devDependencies": {
"@types/node": "^20",
diff --git a/src/components/Contributors/Thant/3d-components/Sphere.jsx b/src/components/Contributors/Thant/3d-components/Sphere.jsx
new file mode 100644
index 0000000..b608b1e
--- /dev/null
+++ b/src/components/Contributors/Thant/3d-components/Sphere.jsx
@@ -0,0 +1,49 @@
+import React, { useEffect, useMemo, useRef } from 'react'
+import fragmentShader from './fragmentShader.js'
+import vertexShader from './vertexShader.js'
+import { useFrame } from '@react-three/fiber'
+import { MathUtils } from 'three'
+import * as THREE from 'three'
+
+const Sphere = ({ sound }) => {
+ const mesh = useRef()
+ const analyser = useRef();
+ useEffect(
+ () => void (analyser.current = new THREE.AudioAnalyser(sound.current, 32)),
+ []
+ );
+ const uniforms = useMemo(() => {
+ return {
+ u_time: { value: 0 },
+ u_intensity: { value: 3 }
+ }
+ })
+ useFrame((state, delta) => {
+ const { clock } = state;
+ if (mesh.current) {
+ mesh.current.material.uniforms.u_time.value = 0.4 * clock.getElapsedTime();
+ mesh.current.material.uniforms.u_intensity.value = MathUtils.lerp(mesh.current.material.uniforms.u_intensity.value, 0.15, 0.02);
+ }
+ if (analyser.current) {
+ const data = analyser.current.getAverageFrequency();
+ mesh.current.scale.x = mesh.current.scale.y = mesh.current.scale.z =
+ (data / 100) * 2;
+ uniforms.u_intensity.value = (data / 100) * 2
+ }
+ mesh.current.rotation.x += 0.005 * delta;
+ mesh.current.rotation.y += 0.005 * delta;
+ })
+
+
+ return (
+
+
+
+
+ )
+}
+
+
+
+export default Sphere
\ No newline at end of file
diff --git a/src/components/Contributors/Thant/3d-components/fragmentShader.js b/src/components/Contributors/Thant/3d-components/fragmentShader.js
new file mode 100644
index 0000000..4835bf3
--- /dev/null
+++ b/src/components/Contributors/Thant/3d-components/fragmentShader.js
@@ -0,0 +1,16 @@
+const fragmentShader = `
+uniform float u_intensity;
+uniform float u_time;
+
+varying vec2 vUv;
+varying float vDisplacement;
+
+void main() {
+ float distort = 2.0 * vDisplacement * u_intensity * sin(vUv.y * 10.0 + u_time);
+ vec3 color = vec3(abs(vUv - 0.5) * 2.0 * (1.0 - distort), 1.0);
+ gl_FragColor = vec4(color, 1.0);
+}
+
+`;
+
+export default fragmentShader;
diff --git a/src/components/Contributors/Thant/3d-components/vertexShader.js b/src/components/Contributors/Thant/3d-components/vertexShader.js
new file mode 100644
index 0000000..0bf4e74
--- /dev/null
+++ b/src/components/Contributors/Thant/3d-components/vertexShader.js
@@ -0,0 +1,109 @@
+const vertexShader = `
+uniform float u_intensity;
+uniform float u_time;
+
+varying vec2 vUv;
+varying float vDisplacement;
+
+// Classic Perlin 3D Noise
+// by Stefan Gustavson
+//
+vec4 permute(vec4 x) {
+ return mod(((x*34.0)+1.0)*x, 289.0);
+}
+
+vec4 taylorInvSqrt(vec4 r) {
+ return 1.79284291400159 - 0.85373472095314 * r;
+}
+
+vec3 fade(vec3 t) {
+ return t*t*t*(t*(t*6.0-15.0)+10.0);
+}
+
+float cnoise(vec3 P) {
+ vec3 Pi0 = floor(P); // Integer part for indexing
+ vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
+ Pi0 = mod(Pi0, 289.0);
+ Pi1 = mod(Pi1, 289.0);
+ vec3 Pf0 = fract(P); // Fractional part for interpolation
+ vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
+ vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
+ vec4 iy = vec4(Pi0.yy, Pi1.yy);
+ vec4 iz0 = Pi0.zzzz;
+ vec4 iz1 = Pi1.zzzz;
+
+ vec4 ixy = permute(permute(ix) + iy);
+ vec4 ixy0 = permute(ixy + iz0);
+ vec4 ixy1 = permute(ixy + iz1);
+
+ vec4 gx0 = ixy0 / 7.0;
+ vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;
+ gx0 = fract(gx0);
+ vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
+ vec4 sz0 = step(gz0, vec4(0.0));
+ gx0 -= sz0 * (step(0.0, gx0) - 0.5);
+ gy0 -= sz0 * (step(0.0, gy0) - 0.5);
+
+ vec4 gx1 = ixy1 / 7.0;
+ vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;
+ gx1 = fract(gx1);
+ vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
+ vec4 sz1 = step(gz1, vec4(0.0));
+ gx1 -= sz1 * (step(0.0, gx1) - 0.5);
+ gy1 -= sz1 * (step(0.0, gy1) - 0.5);
+
+ vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
+ vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
+ vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
+ vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
+ vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
+ vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
+ vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
+ vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
+
+ vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
+ g000 *= norm0.x;
+ g010 *= norm0.y;
+ g100 *= norm0.z;
+ g110 *= norm0.w;
+ vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
+ g001 *= norm1.x;
+ g011 *= norm1.y;
+ g101 *= norm1.z;
+ g111 *= norm1.w;
+
+ float n000 = dot(g000, Pf0);
+ float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
+ float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
+ float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
+ float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
+ float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
+ float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
+ float n111 = dot(g111, Pf1);
+
+ vec3 fade_xyz = fade(Pf0);
+ vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
+ vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
+ float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
+ return 2.2 * n_xyz;
+}
+
+// End of Perlin Noise Code
+
+
+void main() {
+ vUv = uv;
+
+ vDisplacement = cnoise(position + vec3(2.0 * u_time));
+
+ vec3 newPosition = position + normal * (u_intensity * vDisplacement);
+
+ vec4 modelPosition = modelMatrix * vec4(newPosition, 1.0);
+ vec4 viewPosition = viewMatrix * modelPosition;
+ vec4 projectedPosition = projectionMatrix * viewPosition;
+
+ gl_Position = projectedPosition;
+}
+`;
+
+export default vertexShader;
diff --git a/src/components/Contributors/Thant/App.jsx b/src/components/Contributors/Thant/App.jsx
new file mode 100644
index 0000000..87bed9f
--- /dev/null
+++ b/src/components/Contributors/Thant/App.jsx
@@ -0,0 +1,17 @@
+import React, { useEffect, useState } from 'react'
+import VN from './VN'
+import Visualizer from './Visualizer'
+
+const App = () => {
+ const [isClicked, setClick] = useState(false)
+ const [audioTime, setAudioTime] = useState(0)
+ return (
+ <>
+ {
+ isClicked ? :
+ }
+ >
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/src/components/Contributors/Thant/VN.jsx b/src/components/Contributors/Thant/VN.jsx
new file mode 100644
index 0000000..891524b
--- /dev/null
+++ b/src/components/Contributors/Thant/VN.jsx
@@ -0,0 +1,133 @@
+import React, { useEffect, useState } from 'react'
+import dialogArray from './choices.json'
+
+const VN = ({ setClick, setAudioTime }) => {
+ const start = () => {
+ document.getElementById('start').classList.add('hidden')
+ document.getElementById('vn').classList.remove('hidden')
+ let audio = new Audio('https://drive.google.com/uc?id=1vDo02iqo8lOEUhVouXh5FZNOXZh3FzM9')
+ audio.preload = 'auto'
+ audio.volume = 0.5
+ audio.addEventListener("canplay", () => {
+ audio.play();
+ });
+ audio.load();
+ song = audio
+ }
+ let song = null
+ let oneClicked = false;
+ let twoClicked = false;
+ let data = []
+ const nextDialog = () => {
+ if (data.length == 0) {
+ return;
+ }
+ if (data[1] && typeof data[1] != 'string') {
+ if (!data[1].dialog) {
+ choiceBox.classList.toggle('hidden')
+ console.log(data);
+ questionOne.innerHTML = data[1].question1
+ questionTwo.innerHTML = data[1].question2
+ questionOne.addEventListener('click', e => {
+ if (!oneClicked) {
+ choiceBox.classList.toggle('hidden')
+ sprite.src = data[2].answer1.image
+ let typewriter = new Typewriter(dialog, {
+ delay: 50
+ })
+ typewriter.typeString(data[2].answer1.dialog).start()
+ data = data.slice(3)
+ oneClicked = true;
+ }
+ })
+ questionTwo.addEventListener('click', e => {
+ if (!twoClicked) {
+ choiceBox.classList.toggle('hidden')
+ sprite.src = data[2].answer2.image
+ let typewriter = new Typewriter(dialog, {
+ delay: 50
+ })
+ typewriter.typeString(data[2].answer2.dialog).start()
+ data = data.slice(3)
+ twoClicked = true;
+ }
+ })
+ } else {
+ let typewriter = new Typewriter(dialog, {
+ delay: 50
+ })
+ typewriter.typeString(data[0].dialog).start()
+ sprite.src = data[0].image
+ oneClicked = false
+ twoClicked = false
+ data = data.slice(1)
+ }
+ } else {
+ if (data[0] == 'done') {
+ song.volume = 0.3
+ setTimeout(() => {
+ song.volume = 0
+ }, 1000);
+ setClick(true)
+ setAudioTime(song.currentTime)
+ }
+ let typewriter = new Typewriter(dialog, {
+ delay: 50
+ })
+ typewriter.typeString(data[0].dialog).start()
+ sprite.src = data[0].image
+ oneClicked = false
+ twoClicked = false
+ data = data.slice(1)
+ }
+ }
+
+ function lightOff() {
+ document.getElementsByTagName('body')[0].style.background = 'black';
+ }
+
+ useEffect(() => {
+ let dialog = document.getElementById('dialog')
+ data = dialogArray
+ let typewriter = new Typewriter(dialog, {
+ delay: 50
+ })
+ typewriter.typeString(data[0].dialog).start()
+ let choiceBox = document.getElementById('choiceBox')
+ let questionOne = document.getElementById('questionOne')
+ let questionTwo = document.getElementById('questionTwo')
+ let sprite = document.getElementById('sprite')
+ }, [])
+ return (
+ <>
+
+
+
+
+
+
+
+
+ Thant Htet Aung
+
+
+
+
+
+
+
+ Choice One
+
+
+ Choice Two
+
+
+ >
+ )
+}
+
+export default VN
\ No newline at end of file
diff --git a/src/components/Contributors/Thant/Visualizer.jsx b/src/components/Contributors/Thant/Visualizer.jsx
new file mode 100644
index 0000000..6d154cc
--- /dev/null
+++ b/src/components/Contributors/Thant/Visualizer.jsx
@@ -0,0 +1,31 @@
+import React, { Suspense, useEffect, useRef } from 'react'
+import { Canvas } from '@react-three/fiber'
+import Sphere from './3d-components/Sphere'
+import { Environment, OrbitControls, PositionalAudio } from '@react-three/drei'
+import { EffectComposer, Bloom, DepthOfField } from '@react-three/postprocessing'
+
+const Visualizer = ({ audioTime }) => {
+ const sound = useRef();
+ useEffect(() => {
+ document.getElementsByTagName('body')[0].style.background = 'black';
+ }, [])
+ return (
+
+
+
+ )
+}
+
+export default Visualizer
\ No newline at end of file
diff --git a/src/components/Contributors/Thant/audio/space-walk.mp3 b/src/components/Contributors/Thant/audio/space-walk.mp3
new file mode 100644
index 0000000..63b965a
Binary files /dev/null and b/src/components/Contributors/Thant/audio/space-walk.mp3 differ
diff --git a/src/components/Contributors/Thant/choices.json b/src/components/Contributors/Thant/choices.json
new file mode 100644
index 0000000..56fc123
--- /dev/null
+++ b/src/components/Contributors/Thant/choices.json
@@ -0,0 +1,67 @@
+[
+ {
+ "dialog": "ဘာာကိစ္စလည်းခင်ဗျ",
+ "image": "https://i.imgur.com/YUYwLuE.png"
+ },
+ {
+ "question1": "Profileအသေးစိတ်ကဘယ်မှာတုန်း",
+ "question2": "ဒါဘာကြီးလည်း ရှင်းပြပါအုန်း"
+ },
+ {
+ "answer1": {
+ "dialog": "အဲ့တာဆိုရင်တော့ မရေးထားဘူး",
+ "image": "https://i.imgur.com/bLB4Gzp.png"
+ },
+ "answer2": {
+ "dialog": "ဒါက Visual Novelပုံစံကို အတုယူထားတာ",
+ "image": "https://i.imgur.com/bLB4Gzp.png"
+ }
+ },
+ {
+ "dialog": "သူများတွေလိုလည်း Frontend ပရိုမဟုတ်တော့",
+ "image": "https://i.imgur.com/K9TNq53.png"
+ },
+ {
+ "dialog": "စိတ်ဝင်စားစရာကောင်းတဲ့အလန်းစားProfile မျိုးမရေးတတ်ပါဘူး",
+ "image": "https://i.imgur.com/K9TNq53.png"
+ },
+ {
+ "dialog": "ဒီအတိုင်းကြီး Plainပဲရေးရမှာလည်း ပျင်းဖို့ကောင်းတာဆိုတော့",
+ "image": "https://i.imgur.com/z5mBEFq.png"
+ },
+ {
+ "dialog": "နည်းနည်းလောက် လက်ဆော့လိုက်တယ်ဆိုတာမျိုးပေါ့",
+ "image": "https://i.imgur.com/fJvnZAH.png"
+ },
+ {
+ "question1": "ရေးထားတာလေး ကောင်းပါတယ်",
+ "question2": "ပျင်းဖို့ကောင်းတယ်"
+ },
+ {
+ "answer1": {
+ "dialog": "ကျေးဇူးပါ ဒါပေမယ့်",
+ "image": "https://i.imgur.com/OWFb6q5.png"
+ },
+ "answer2": {
+ "dialog": "မငြင်းနိုင်ပါဘူး",
+ "image": "https://i.imgur.com/bLB4Gzp.png"
+ }
+ },
+ {
+ "dialog": "Reactဆိုလည်း Basicလောက်ပဲရေးနိုင်တာဆိုတော့ ကောင်းတယ်လို့ပြောဖို့ကခက်မယ်ထင်ပါတယ်",
+ "image": "https://i.imgur.com/fJvnZAH.png"
+ },
+ {
+ "dialog": "လက်ရှိမှာလည်း Junior Laravel Developerအနေနဲ့အလုပ်လုပ်နေတာ တစ်နှစ်တောင်မပြည့်သေးဘူးဆိုတော့",
+ "image": "https://i.imgur.com/bLB4Gzp.png"
+ },
+ {
+ "dialog": "ထပ်ထပ် သင်ယူပြီး ပိုလန်း ပိုမိုက်တဲ့ Codeတွေရေးနိုင်အောင် ကြိုးစားသွားမှာပါ",
+ "image": "https://i.imgur.com/fJvnZAH.png"
+ },
+ {
+ "dialog": "သီချင်းသံတိုးနေရင်တော့ Mouse Wheelနဲ့ချဲ့လို့ရပါတယ်နော်",
+ "image": "https://i.imgur.com/fJvnZAH.png"
+ },
+ "done"
+]
\ No newline at end of file