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 ( + <> +
+
+ Start +
+
+
+
+ +
+
+
+
+ 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