Try adding black hole background
This commit is contained in:
code002lover 2025-12-06 13:49:52 +01:00
parent 59b23586bc
commit 4e91349a59
4 changed files with 1153 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import { PersonDetails } from "./PersonDetails";
import { GameList } from "./GameList";
import { GameFilter } from "./GameFilter";
import { GameDetails } from "./GameDetails";
import { ShaderBackground } from "./ShaderBackground";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import "./App.css";
import { apiFetch } from "./api";
@ -15,6 +16,15 @@ function App() {
const [token, setToken] = useState<string>(
localStorage.getItem("token") || ""
);
const [isShaderTheme, setIsShaderTheme] = useState<boolean>(false);
useEffect(() => {
if (isShaderTheme) {
document.body.classList.add("shader-theme");
} else {
document.body.classList.remove("shader-theme");
}
}, [isShaderTheme]);
const fetchPeople = () => {
if (!token) return;
@ -66,7 +76,15 @@ function App() {
<button onClick={handleLogout} className="btn-secondary">
Logout
</button>
<button
onClick={() => setIsShaderTheme(!isShaderTheme)}
className="btn-secondary"
style={{ marginLeft: "1rem" }}
>
{isShaderTheme ? "Normal Theme" : "Shader Theme"}
</button>
</div>
{isShaderTheme && <ShaderBackground />}
<Routes>
<Route path="/" element={<PersonList people={people} />} />
<Route path="/games" element={<GameList />} />

File diff suppressed because it is too large Load Diff

View File

@ -88,7 +88,21 @@ input:focus, select:focus {
border-color: transparent;
}
ul {
list-style: none;
padding: 0;
}
.shader-theme {
--primary-bg: transparent; /* Let the shader show through */
--secondary-bg: rgba(0, 0, 0, 0.7); /* Translucent cards */
--secondary-alt-bg: rgba(20, 20, 20, 0.6); /* Translucent inputs */
--tertiary-bg: rgba(40, 40, 40, 0.8);
--border-color: rgba(255, 255, 255, 0.15);
--text-color: #ffffff;
}
.shader-theme body {
background-color: transparent;
}

View File

@ -0,0 +1,93 @@
export function generateRandomRGBABytes(
width: number,
height: number
): Uint8Array {
if (width <= 0 || height <= 0) {
throw new Error("width and height must be positive");
}
const len = width * height * 4;
const out = new Uint8Array(len);
// Maximum bytes per getRandomValues call (per spec / browsers)
const MAX_GETRANDOM_BYTES = 65536;
if (typeof crypto !== "undefined" && "getRandomValues" in crypto) {
// Fill in chunks of up to MAX_GETRANDOM_BYTES
let offset = 0;
while (offset < len) {
const chunkSize = Math.min(MAX_GETRANDOM_BYTES, len - offset);
// Subarray view for the current chunk
const chunkView = out.subarray(offset, offset + chunkSize);
crypto.getRandomValues(chunkView);
offset += chunkSize;
}
// Ensure alpha channel is fully opaque (255)
for (let i = 3; i < len; i += 4) out[i] = 255;
} else {
// Fallback to Math.random for all bytes
for (let i = 0; i < len; i++) {
if ((i + 1) % 4 === 0) out[i] = 255;
else out[i] = Math.floor(Math.random() * 256);
}
}
return out;
}
/**
* Create a WebGL texture from random data and bind it to texture unit 0,
* then set the sampler2D uniform named `iChannel0` to use unit 0.
*
* gl: WebGLRenderingContext or WebGL2RenderingContext
* program: compiled & linked shader program (must be in use or will be used)
*/
export function createAndBindRandomTextureToIChannel0(
gl: WebGLRenderingContext | WebGL2RenderingContext,
program: WebGLProgram,
width: number,
height: number
): WebGLTexture {
const bytes = generateRandomRGBABytes(width, height);
const tex = gl.createTexture();
if (!tex) throw new Error("Failed to create texture");
// Activate texture unit 0 and bind the texture
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex);
// Texture parameters suitable for data textures
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// Upload pixel data as RGBA UNSIGNED_BYTE
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
width,
height,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
bytes
);
const location = gl.getUniformLocation(program, "iChannel0");
if (location === null) {
// Clean up binding and return but signal with thrown error if desired
gl.bindTexture(gl.TEXTURE_2D, null);
throw new Error("Uniform 'iChannel0' not found in program");
}
// Set sampler uniform to texture unit 0
gl.uniform1i(location, 0);
// Unbind the texture if you prefer (not strictly necessary)
gl.bindTexture(gl.TEXTURE_2D, null);
return tex;
}