QOL dimming shader
This commit is contained in:
24
index.html
24
index.html
@@ -101,29 +101,6 @@
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
/* cycle button */
|
||||
#cycle-button {
|
||||
font: inherit;
|
||||
font-size: clamp(0.8rem, 1.4vw, 1rem);
|
||||
letter-spacing: 0.1em;
|
||||
padding: 0.7rem 2.4rem;
|
||||
background: rgba(22, 48, 78, 0.35);
|
||||
border: 1.5px solid rgba(144, 184, 220, 0.6);
|
||||
color: #fff;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
backdrop-filter: blur(2px);
|
||||
transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
#cycle-button:hover {
|
||||
background: rgba(40, 90, 140, 0.5);
|
||||
border-color: rgba(180, 210, 240, 0.9);
|
||||
box-shadow: 0 0 18px rgba(90, 170, 255, 0.4);
|
||||
}
|
||||
#cycle-button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
/* ---------- resume section ---------- */
|
||||
@keyframes resumeFadeIn {
|
||||
from { opacity: 0; transform: translateX(-50%) translateY(18px); }
|
||||
@@ -481,7 +458,6 @@
|
||||
<h2 id="scene-subtitle"></h2>
|
||||
<p id="scene-body"></p>
|
||||
</div>
|
||||
<button id="cycle-button">NEXT</button>
|
||||
<div id="resume-section"></div>
|
||||
<div id="projects-section"></div>
|
||||
</div>
|
||||
|
||||
20
src/app.ts
20
src/app.ts
@@ -2,7 +2,8 @@ import { Renderer, UiState } from './engine/renderer'
|
||||
import { Input } from './ui/input'
|
||||
import { DomOverlay } from './ui/overlay'
|
||||
import { Router, Route } from './router'
|
||||
import { PAGES, PROJECTS_SCENE, RESUME_SCENE } from './data/pages'
|
||||
import { PROJECTS_SCENE, RESUME_SCENE } from './data/pages'
|
||||
import { SCENES } from './data/scenes'
|
||||
|
||||
const DPR_CAP = 2
|
||||
|
||||
@@ -31,21 +32,10 @@ export class App {
|
||||
async start(): Promise<boolean> {
|
||||
this.input = new Input()
|
||||
|
||||
// Build SceneContent[] from PAGES for the overlay
|
||||
const scenes = PAGES.map((p) => ({
|
||||
title: p.title,
|
||||
subtitle: p.subtitle,
|
||||
body: p.body,
|
||||
}))
|
||||
|
||||
this.overlay = new DomOverlay(scenes, {
|
||||
this.overlay = new DomOverlay(SCENES, {
|
||||
onNavClick: (s) => {
|
||||
this.router.navigate(Router.sceneToBasePath(s))
|
||||
},
|
||||
onButtonClick: () => {
|
||||
const next = (this.scene + 1) % 4
|
||||
this.router.navigate(Router.sceneToBasePath(next))
|
||||
},
|
||||
onNavigate: (path) => {
|
||||
this.router.navigate(path)
|
||||
},
|
||||
@@ -142,11 +132,15 @@ export class App {
|
||||
|
||||
this.computeStemMultipliers(time)
|
||||
|
||||
// dim the shader when on any non-home scene
|
||||
const dim = this.scene === 0 ? 0.0 : 0.4
|
||||
|
||||
const state: UiState = {
|
||||
resolution: this.res,
|
||||
time,
|
||||
scene: this.scene,
|
||||
mouse: this.mouse,
|
||||
dim,
|
||||
stemMultipliers: this.stemMultipliers,
|
||||
}
|
||||
this.renderer.render(state)
|
||||
|
||||
@@ -2,6 +2,6 @@ import type { SceneContent } from './index'
|
||||
|
||||
export const about: SceneContent = {
|
||||
title: 'ABOUT',
|
||||
subtitle: 'Who I am',
|
||||
subtitle: 'Who I am and what I do',
|
||||
body: 'My name is Ahmed Alaa Ahmed Mohamed (aka Djoser/Djosen/Inedited), I\'m a passionate creative software engineer and game developer. ',
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface UiState {
|
||||
time: number
|
||||
scene: number
|
||||
mouse: Float32Array
|
||||
dim: number
|
||||
stemMultipliers: Float32Array
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ export class Renderer {
|
||||
d[4] = state.mouse[0]
|
||||
d[5] = state.mouse[1]
|
||||
// d[6], d[7]: padding — left as zero
|
||||
// d[8]-d[11]: date — left as zero
|
||||
d[8] = state.dim // u.date.x — dim factor for non-home scenes
|
||||
// d[12]-d[15]: sampleRate — left as zero
|
||||
d.set(state.stemMultipliers, 16)
|
||||
this.device.queue.writeBuffer(this.uniformBuffer, 0, this.uniformData)
|
||||
|
||||
@@ -100,5 +100,9 @@ fn fs(in: VsOut) -> @location(0) vec4<f32> {
|
||||
// soft cursor glow
|
||||
finalColor += exp(-distMouse * 4.0) * 0.03 * sceneAccent;
|
||||
|
||||
// ---------- dim when not on the home page (u.date.x controls it) ----------
|
||||
let dim = u.date.x;
|
||||
finalColor = mix(finalColor, vec3<f32>(0.0), dim);
|
||||
|
||||
return vec4<f32>(finalColor * vignette, 1.0);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ interface SceneContent {
|
||||
|
||||
export interface OverlayCallbacks {
|
||||
onNavClick: (scene: number) => void
|
||||
onButtonClick: () => void
|
||||
onNavigate: (path: string) => void
|
||||
}
|
||||
|
||||
@@ -139,7 +138,6 @@ export class DomOverlay {
|
||||
private readonly sceneContentEl: HTMLElement
|
||||
private readonly projectsSectionEl: HTMLElement
|
||||
private readonly resumeSectionEl: HTMLElement
|
||||
private readonly cycleBtnEl: HTMLElement
|
||||
private readonly scenes: SceneContent[]
|
||||
|
||||
constructor(scenes: SceneContent[], callbacks: OverlayCallbacks) {
|
||||
@@ -151,14 +149,11 @@ export class DomOverlay {
|
||||
this.sceneContentEl = document.getElementById('scene-content') as HTMLElement
|
||||
this.projectsSectionEl = document.getElementById('projects-section') as HTMLElement
|
||||
this.resumeSectionEl = document.getElementById('resume-section') as HTMLElement
|
||||
this.cycleBtnEl = document.getElementById('cycle-button') as HTMLElement
|
||||
|
||||
this.navItems.forEach((item, i) => {
|
||||
item.addEventListener('click', () => callbacks.onNavClick(i))
|
||||
})
|
||||
|
||||
this.cycleBtnEl.addEventListener('click', () => callbacks.onButtonClick())
|
||||
|
||||
// delegate clicks inside projects section → onNavigate callback
|
||||
this.projectsSectionEl.addEventListener('click', (e) => {
|
||||
const target = e.target as HTMLElement
|
||||
@@ -227,16 +222,13 @@ export class DomOverlay {
|
||||
this.sceneContentEl.classList.remove('hidden')
|
||||
this.projectsSectionEl.classList.remove('visible')
|
||||
this.resumeSectionEl.classList.remove('visible')
|
||||
this.cycleBtnEl.style.display = ''
|
||||
|
||||
if (scene === PROJECTS_SCENE) {
|
||||
this.sceneContentEl.classList.add('hidden')
|
||||
this.projectsSectionEl.classList.add('visible')
|
||||
this.cycleBtnEl.style.display = 'none'
|
||||
} else if (scene === RESUME_SCENE) {
|
||||
this.sceneContentEl.classList.add('hidden')
|
||||
this.resumeSectionEl.classList.add('visible')
|
||||
this.cycleBtnEl.style.display = 'none'
|
||||
}
|
||||
|
||||
this.navItems.forEach((item, i) => {
|
||||
|
||||
Reference in New Issue
Block a user