update
This commit is contained in:
BIN
app/security/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
app/security/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/security/__pycache__/security.cpython-311.pyc
Normal file
BIN
app/security/__pycache__/security.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -16,3 +16,9 @@ async def pigeonhole_principle_simulation(request: Request):
|
|||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
request=request, name="pigeonhole.html"
|
request=request, name="pigeonhole.html"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@security_router.get("/noise-letter")
|
||||||
|
async def noise_letter_visualization(request: Request):
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
request=request, name="noise_letter.html"
|
||||||
|
)
|
||||||
180
app/static/js/noise_letter.js
Normal file
180
app/static/js/noise_letter.js
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
|
||||||
|
async function loadFile(url) {
|
||||||
|
const res = await fetch(url);
|
||||||
|
return res.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileShader(gl, source, type) {
|
||||||
|
const shader = gl.createShader(type);
|
||||||
|
gl.shaderSource(shader, source);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
console.error('Shader compile error:', gl.getShaderInfoLog(shader));
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTexture(gl) {
|
||||||
|
const tex = gl.createTexture();
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||||
|
// Set parameters so we can handle non-power-of-2 images if needed
|
||||||
|
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);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updateCharTexture(gl, texture, text) {
|
||||||
|
const height = 256;
|
||||||
|
// Dynamic width based on text length, min 1
|
||||||
|
const chars = Math.max(1, text.length);
|
||||||
|
const width = 256 * chars;
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
ctx.fillStyle = 'white';
|
||||||
|
ctx.font = 'bold 200px monospace';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
ctx.fillText(text, width / 2, height / 2);
|
||||||
|
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
|
||||||
|
|
||||||
|
return chars; // Return aspect ratio (width/height)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const canvas = document.getElementById('glcanvas');
|
||||||
|
const gl = canvas.getContext('webgl');
|
||||||
|
|
||||||
|
if (!gl) {
|
||||||
|
alert('WebGL not supported');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Shaders
|
||||||
|
const vsSource = await loadFile('/static/shaders/vertex.glsl');
|
||||||
|
// Using simple Cache Busting for reloading shader during dev if needed, but not strictly necessary here
|
||||||
|
const fsSource = await loadFile('/static/shaders/fragment.glsl');
|
||||||
|
|
||||||
|
const vs = compileShader(gl, vsSource, gl.VERTEX_SHADER);
|
||||||
|
const fs = compileShader(gl, fsSource, gl.FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
const program = gl.createProgram();
|
||||||
|
gl.attachShader(program, vs);
|
||||||
|
gl.attachShader(program, fs);
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||||
|
console.error('Program link error:', gl.getProgramInfoLog(program));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.useProgram(program);
|
||||||
|
|
||||||
|
// Quad Buffer
|
||||||
|
const verts = new Float32Array([
|
||||||
|
-1, -1,
|
||||||
|
1, -1,
|
||||||
|
-1, 1,
|
||||||
|
-1, 1,
|
||||||
|
1, -1,
|
||||||
|
1, 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const buffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
const posLoc = gl.getAttribLocation(program, 'position');
|
||||||
|
gl.enableVertexAttribArray(posLoc);
|
||||||
|
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
const uTime = gl.getUniformLocation(program, 'u_time');
|
||||||
|
const uRes = gl.getUniformLocation(program, 'u_resolution');
|
||||||
|
const uCharPos = gl.getUniformLocation(program, 'u_charPos');
|
||||||
|
const uCharSize = gl.getUniformLocation(program, 'u_charSize');
|
||||||
|
// Texture uniform usually defaults to 0, which is fine
|
||||||
|
|
||||||
|
// State
|
||||||
|
const charTexture = createTexture(gl);
|
||||||
|
|
||||||
|
let charX = 0.5;
|
||||||
|
let charY = 0.5;
|
||||||
|
let charW = 0.5;
|
||||||
|
let charH = 0.5;
|
||||||
|
|
||||||
|
let currentAspect = 1.0;
|
||||||
|
|
||||||
|
// UI Handling
|
||||||
|
const input = document.getElementById('textInput');
|
||||||
|
const btn = document.getElementById('renderBtn');
|
||||||
|
|
||||||
|
function updateText() {
|
||||||
|
// Use placeholder or "A" if empty to avoid 0 size
|
||||||
|
let text = input.value.toUpperCase().substring(0, 12);
|
||||||
|
if (text.length === 0) return;
|
||||||
|
|
||||||
|
currentAspect = updateCharTexture(gl, charTexture, text);
|
||||||
|
resize(); // Recalculate size
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.addEventListener('click', updateText);
|
||||||
|
|
||||||
|
// Initial Text
|
||||||
|
currentAspect = updateCharTexture(gl, charTexture, "HELLO");
|
||||||
|
|
||||||
|
function resize() {
|
||||||
|
// Look up container size
|
||||||
|
const container = canvas.parentElement;
|
||||||
|
canvas.width = container.clientWidth;
|
||||||
|
canvas.height = container.clientHeight;
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Adjust aspect ratio
|
||||||
|
const screenAspect = canvas.width / canvas.height;
|
||||||
|
|
||||||
|
// Target: charW / charH = currentAspect / screenAspect
|
||||||
|
|
||||||
|
// Try filling 60% of height
|
||||||
|
charH = 0.6;
|
||||||
|
charW = charH * currentAspect / screenAspect;
|
||||||
|
|
||||||
|
// Constrain width to 95%
|
||||||
|
if (charW > 0.95) {
|
||||||
|
charW = 0.95;
|
||||||
|
charH = charW * screenAspect / currentAspect;
|
||||||
|
}
|
||||||
|
|
||||||
|
charX = 0.5 - charW / 2;
|
||||||
|
charY = 0.5 - charH / 2;
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', resize);
|
||||||
|
resize();
|
||||||
|
|
||||||
|
function render(time) {
|
||||||
|
time *= 0.001; // Seconds
|
||||||
|
|
||||||
|
gl.uniform1f(uTime, time);
|
||||||
|
gl.uniform2f(uRes, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
gl.uniform2f(uCharPos, charX, charY); // uniform needs bottom-left
|
||||||
|
gl.uniform2f(uCharSize, charW, charH);
|
||||||
|
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||||
|
requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
58
app/static/shaders/fragment.glsl
Normal file
58
app/static/shaders/fragment.glsl
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
uniform float u_time;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform sampler2D u_charTexture;
|
||||||
|
uniform vec2 u_charPos; // Normalized 0-1 (Bottom-Left)
|
||||||
|
uniform vec2 u_charSize; // Normalized 0-1 (Width, Height)
|
||||||
|
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
// reliable pseudo-random hash
|
||||||
|
float random(vec2 p) {
|
||||||
|
vec3 p3 = fract(vec3(p.xyx) * .1031);
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.x + p3.y) * p3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Correct UV for aspect ratio if needed, but here we work in screen space mostly
|
||||||
|
|
||||||
|
// Background Noise
|
||||||
|
// Use floor to ensure we are sampling integer grid, making it purely pixel-noise
|
||||||
|
vec2 gridPos = floor(gl_FragCoord.xy);
|
||||||
|
float bgNoise = random(gridPos);
|
||||||
|
float val = step(0.5, bgNoise);
|
||||||
|
|
||||||
|
// Character Composition
|
||||||
|
vec2 charEnd = u_charPos + u_charSize;
|
||||||
|
bool inBox = (vUv.x >= u_charPos.x && vUv.x <= charEnd.x &&
|
||||||
|
vUv.y >= u_charPos.y && vUv.y <= charEnd.y);
|
||||||
|
|
||||||
|
if (inBox) {
|
||||||
|
vec2 texUv = (vUv - u_charPos) / u_charSize;
|
||||||
|
texUv.y = 1.0 - texUv.y;
|
||||||
|
|
||||||
|
vec4 texColor = texture2D(u_charTexture, texUv);
|
||||||
|
|
||||||
|
// Hard threshold to avoid any smooth edges revealing the shape
|
||||||
|
if (texColor.a > 0.5) {
|
||||||
|
// Inner Character Noise - Scrolls Down
|
||||||
|
float scrollSpeed = 200.0;
|
||||||
|
// Calculate scrolled position
|
||||||
|
vec2 scrollCoords = gl_FragCoord.xy;
|
||||||
|
scrollCoords.y += u_time * scrollSpeed;
|
||||||
|
|
||||||
|
// IMPORTANT: Floor the scrolled coordinates!
|
||||||
|
// This ensures the noise "pixels" look exactly like the background "pixels" in size and sharpness.
|
||||||
|
// If we don't floor, we get sub-pixel sampling which might look different (smooth/shimmering).
|
||||||
|
vec2 charGridPos = floor(scrollCoords);
|
||||||
|
|
||||||
|
// Use different seed offset to distinguish content, but same distribution
|
||||||
|
float charNoise = random(charGridPos + vec2(42.0, 99.0));
|
||||||
|
val = step(0.5, charNoise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = vec4(vec3(1.0 - val), 1.0);
|
||||||
|
}
|
||||||
7
app/static/shaders/vertex.glsl
Normal file
7
app/static/shaders/vertex.glsl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
attribute vec2 position;
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vUv = position * 0.5 + 0.5;
|
||||||
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
|
}
|
||||||
64
app/templates/noise_letter.html
Normal file
64
app/templates/noise_letter.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Noise Letter{% endblock %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
<style>
|
||||||
|
.noise-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 80vh;
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
font-family: monospace;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
height: 400px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="noise-wrapper rounded-lg">
|
||||||
|
<div id="controls">
|
||||||
|
<input type="text" id="textInput" maxlength="12" placeholder="ENTER TEXT (MAX 12)"
|
||||||
|
class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 placeholder-gray-400">
|
||||||
|
<button id="renderBtn"
|
||||||
|
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
|
||||||
|
RENDER
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<canvas id="glcanvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4 text-gray-600 text-sm">Visualizing text as noise signal</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
<script src="{{ url_for('static', path='js/noise_letter.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user