Files
bitfielder/index.html
2025-07-05 01:07:53 +00:00

514 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bitfielder</title>
<meta name="description" content="Bitfielder is a live bitfield shader editor for creating visual patterns using bitwise operations.">
<meta name="author" content="BuboBubo">
<meta name="keywords" content="shader, bitfield, visual, patterns, programming, interactive, editor">
<meta property="og:title" content="Bitfielder - Bitfield Shader App">
<meta property="og:description" content="Interactive bitfield shader editor for creating visual patterns using bitwise operations">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Bitfielder - Bitfield Shader App">
<meta name="twitter:description" content="Interactive bitfield shader editor for creating visual patterns using bitwise operations">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #000;
color: #fff;
font-family: monospace;
overflow: hidden;
}
#canvas {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
image-rendering: pixelated;
image-rendering: -moz-crisp-edges;
image-rendering: crisp-edges;
}
#topbar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 40px;
background: rgba(0, 0, 0, 0.8);
border-bottom: 1px solid #333;
display: flex;
align-items: center;
padding: 0 20px;
z-index: 100;
}
#topbar .title {
color: #fff;
font-size: 14px;
font-weight: bold;
margin-right: 20px;
}
#topbar .controls {
display: flex;
gap: 10px;
margin-left: auto;
}
#topbar button {
background: rgba(255, 255, 255, 0.1);
border: 1px solid #555;
color: #fff;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-family: monospace;
font-size: 12px;
}
#topbar button:hover {
background: rgba(255, 255, 255, 0.2);
}
#editor-panel {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 140px;
background: rgba(0, 0, 0, 0.6);
border-top: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
z-index: 100;
backdrop-filter: blur(5px);
transition: all 0.3s ease;
}
#editor-panel.minimal {
height: 50px;
bottom: 20px;
left: 20px;
right: 20px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
#editor {
width: 100%;
background: rgba(0, 0, 0, 0.3);
border: none;
color: #fff;
font-family: monospace;
font-size: 16px;
padding: 15px;
resize: none;
outline: none;
transition: all 0.3s ease;
}
#editor.minimal {
padding: 12px 15px;
font-size: 14px;
background: rgba(0, 0, 0, 0.3);
}
#help-popup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.95);
border: 1px solid #555;
border-radius: 8px;
padding: 30px;
z-index: 1000;
max-width: 500px;
display: none;
}
#help-popup h3 {
margin-bottom: 20px;
color: #fff;
font-size: 18px;
}
#help-popup .help-section {
margin-bottom: 20px;
}
#help-popup .help-section h4 {
color: #ccc;
margin-bottom: 10px;
font-size: 14px;
}
#help-popup .help-section p {
color: #999;
font-size: 12px;
line-height: 1.5;
margin-bottom: 8px;
}
#help-popup .close-btn {
position: absolute;
top: 10px;
right: 15px;
background: none;
border: none;
color: #999;
font-size: 20px;
cursor: pointer;
}
.hidden {
display: none !important;
}
#show-ui-btn {
position: fixed;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.7);
border: 1px solid #555;
color: #fff;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
font-family: monospace;
font-size: 12px;
z-index: 1000;
display: none;
}
#show-ui-btn:hover {
background: rgba(0, 0, 0, 0.9);
}
#shader-library {
position: fixed;
top: 0;
right: -300px;
width: 300px;
height: 100vh;
background: rgba(0, 0, 0, 0.9);
border-left: 1px solid rgba(255, 255, 255, 0.1);
z-index: 90;
transition: right 0.3s ease;
backdrop-filter: blur(10px);
overflow-y: auto;
}
#shader-library-trigger {
position: fixed;
top: 0;
right: 0;
width: 20px;
height: 100vh;
z-index: 91;
cursor: pointer;
}
#shader-library-trigger:hover + #shader-library,
#shader-library:hover {
right: 0;
}
#shader-library.open {
right: 0;
}
.library-header {
padding: 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.library-header h3 {
margin: 0 0 15px 0;
color: #fff;
font-size: 16px;
}
.save-shader {
display: flex;
gap: 8px;
margin-bottom: 15px;
}
.search-shader {
margin-bottom: 10px;
}
.search-shader input {
width: 100%;
background: rgba(255, 255, 255, 0.1);
border: 1px solid #555;
color: #fff;
padding: 6px 8px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
}
.search-shader input::placeholder {
color: #999;
}
.save-shader input {
flex: 1;
background: rgba(255, 255, 255, 0.1);
border: 1px solid #555;
color: #fff;
padding: 6px 8px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
}
.save-shader button {
background: rgba(255, 255, 255, 0.1);
border: 1px solid #555;
color: #fff;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-family: monospace;
font-size: 12px;
}
.save-shader button:hover {
background: rgba(255, 255, 255, 0.2);
}
.shader-list {
padding: 0 20px 20px 20px;
}
.shader-item {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
margin-bottom: 8px;
overflow: hidden;
}
.shader-item-header {
padding: 10px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.shader-item-header:hover {
background: rgba(255, 255, 255, 0.1);
}
.shader-name {
color: #fff;
font-size: 12px;
font-weight: bold;
}
.shader-actions {
display: flex;
gap: 4px;
}
.shader-action {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #ccc;
cursor: pointer;
font-size: 10px;
padding: 4px 6px;
border-radius: 3px;
transition: all 0.2s ease;
font-family: monospace;
}
.shader-action:hover {
background: rgba(255, 255, 255, 0.2);
color: #fff;
transform: scale(1.05);
}
.shader-action.rename {
background: rgba(52, 152, 219, 0.3);
border-color: rgba(52, 152, 219, 0.5);
}
.shader-action.rename:hover {
background: rgba(52, 152, 219, 0.5);
}
.shader-action.delete {
background: rgba(231, 76, 60, 0.3);
border-color: rgba(231, 76, 60, 0.5);
}
.shader-action.delete:hover {
background: rgba(231, 76, 60, 0.5);
}
.shader-code {
padding: 8px 10px;
background: rgba(0, 0, 0, 0.3);
color: #ccc;
font-family: monospace;
font-size: 11px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
word-break: break-all;
}
#performance-warning {
position: fixed;
top: 50px;
right: 20px;
background: rgba(255, 0, 0, 0.8);
color: #fff;
padding: 10px 15px;
border-radius: 4px;
font-size: 12px;
z-index: 1001;
display: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<button id="show-ui-btn">Show UI</button>
<div id="topbar">
<div class="title">Bitfielder</div>
<div class="controls">
<label style="color: #ccc; font-size: 12px; margin-right: 10px;">
Resolution:
<select id="resolution-select" style="background: rgba(255,255,255,0.1); border: 1px solid #555; color: #fff; padding: 4px; border-radius: 4px;">
<option value="1">Full (1x)</option>
<option value="2">Half (2x)</option>
<option value="4">Quarter (4x)</option>
<option value="8">Eighth (8x)</option>
</select>
</label>
<label style="color: #ccc; font-size: 12px; margin-right: 10px;">
FPS:
<select id="fps-select" style="background: rgba(255,255,255,0.1); border: 1px solid #555; color: #fff; padding: 4px; border-radius: 4px;">
<option value="15">15 FPS</option>
<option value="30" selected>30 FPS</option>
<option value="60">60 FPS</option>
</select>
</label>
<label style="color: #ccc; font-size: 12px; margin-right: 10px;">
Render Mode:
<select id="render-mode-select" style="background: rgba(255,255,255,0.1); border: 1px solid #555; color: #fff; padding: 4px; border-radius: 4px;">
<option value="classic" selected>Classic</option>
<option value="grayscale">Grayscale</option>
<option value="red">Red Channel</option>
<option value="green">Green Channel</option>
<option value="blue">Blue Channel</option>
<option value="rgb">RGB Split</option>
<option value="hsv">HSV</option>
<option value="rainbow">Rainbow</option>
</select>
</label>
<button id="help-btn">?</button>
<button id="fullscreen-btn">Fullscreen</button>
<button id="hide-ui-btn">Hide UI</button>
<button id="random-btn">Random</button>
<button id="share-btn">Share</button>
<button id="export-png-btn">Export PNG</button>
</div>
</div>
<div id="editor-panel">
<textarea id="editor" placeholder="Enter shader code... (x, y, t, i, mouseX, mouseY)" spellcheck="false">x^y</textarea>
</div>
<div id="shader-library-trigger"></div>
<div id="shader-library">
<div class="library-header">
<h3>Shader Library</h3>
<div class="save-shader">
<input type="text" id="shader-name-input" placeholder="Shader name..." maxlength="30">
<button id="save-shader-btn">Save</button>
</div>
<div class="search-shader">
<input type="text" id="shader-search-input" placeholder="Search shaders...">
</div>
</div>
<div class="shader-list" id="shader-list">
<!-- Saved shaders will appear here -->
</div>
</div>
<div id="help-popup">
<button class="close-btn">&times;</button>
<h3>Bitfielder Help</h3>
<div class="help-section">
<h4>Keyboard Shortcuts</h4>
<p><strong>Ctrl+Enter</strong> - Execute shader code</p>
<p><strong>F11</strong> - Toggle fullscreen</p>
<p><strong>H</strong> - Hide/show UI</p>
<p><strong>R</strong> - Generate random shader</p>
<p><strong>S</strong> - Share current shader (copy URL)</p>
<p><strong>?</strong> - Show this help</p>
</div>
<div class="help-section">
<h4>Shader Library</h4>
<p>Hover over the <strong>right edge</strong> of the screen to access the shader library</p>
<p>Save shaders with custom names and search through them</p>
<p>Use <strong>edit</strong> to rename, <strong>del</strong> to delete</p>
</div>
<div class="help-section">
<h4>Variables</h4>
<p><strong>x, y</strong> - Pixel coordinates</p>
<p><strong>t</strong> - Time (enables animation)</p>
<p><strong>i</strong> - Pixel index</p>
<p><strong>mouseX, mouseY</strong> - Mouse position (0.0 to 1.0)</p>
</div>
<div class="help-section">
<h4>Operators</h4>
<p><strong>^ & |</strong> - XOR, AND, OR</p>
<p><strong>&lt;&lt; &gt;&gt;</strong> - Bit shift left/right</p>
<p><strong>+ - * / %</strong> - Math operations</p>
</div>
<div class="help-section">
<h4>Render Modes</h4>
<p><strong>Classic</strong> - Original colorful mode</p>
<p><strong>Grayscale</strong> - Black and white</p>
<p><strong>Red/Green/Blue</strong> - Single color channels</p>
<p><strong>HSV</strong> - Hue-based coloring</p>
<p><strong>Rainbow</strong> - Spectrum coloring</p>
</div>
<div class="help-section">
<h4>Export</h4>
<p><strong>Export PNG</strong> - Save current frame as image</p>
</div>
</div>
<div id="performance-warning">
Performance warning: Shader taking too long to render!
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>